<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>yakov.dev Blog</title>
        <link>https://yakov.dev/</link>
        <description>yakov.dev Blog</description>
        <lastBuildDate>Wed, 24 Sep 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Copyright © 2026 Yakov Rakhamimov. Built with Docusaurus.</copyright>
        <item>
            <title><![CDATA[The Moment for Git Worktrees]]></title>
            <link>https://yakov.dev/the-moment-for-git-worktrees</link>
            <guid>https://yakov.dev/the-moment-for-git-worktrees</guid>
            <pubDate>Wed, 24 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Git worktrees let you work on multiple branches simultaneously in separate directories. AI agents make this powerful but complex feature finally practical for everyday development.]]></description>
            <content:encoded><![CDATA[<div class="container_ag6H"><span class="textWrapper_Mwbw"><p>Photo by <a href="https://www.pexels.com/@jahoo/">Jahoo Clouseau</a> from <a href="https://www.pexels.com/photo/worm-s-eye-view-of-church-446618/">Pexels</a></p></span></div>
<p><img decoding="async" loading="lazy" alt="image" src="https://yakov.dev/assets/images/pexels-jahoo-446618-9fe5fc94e53533eb0cee1015bf32cf41.jpg" width="1280" height="675" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-are-git-worktrees">What are Git Worktrees?<a href="https://yakov.dev/the-moment-for-git-worktrees#what-are-git-worktrees" class="hash-link" aria-label="Direct link to What are Git Worktrees?" title="Direct link to What are Git Worktrees?" translate="no">​</a></h2>
<p>Git worktrees are a feature that allows you to have multiple working directories from the same repository, each potentially on different branches. Think of it as having multiple "copies" of your project that all share the same Git history but can work on different branches simultaneously.</p>
<p>When you initialize a Git repository, you get your main worktree (the directory where you ran <code>git init</code> or <code>git clone</code>). From there, you can create additional worktrees that are linked to the same repository but exist in separate directories.</p>
<p>Here are the essential commands you'll need:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># Create a new worktree for a specific branch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">git worktree add ../my-feature</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># List all worktrees</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">git worktree list</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Remove a worktree when you're done with it</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">git worktree remove ../my-feature</span><br></div></code></pre></div></div>
<p>The relationship is simple: your original repository remains the "main" worktree, and any additional worktrees are linked to it. They all share the same <code>.git</code> directory, which means commits, branches, and history are synchronized across all worktrees.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-is-it-different-from-regular-branches">How is it different from regular branches?<a href="https://yakov.dev/the-moment-for-git-worktrees#how-is-it-different-from-regular-branches" class="hash-link" aria-label="Direct link to How is it different from regular branches?" title="Direct link to How is it different from regular branches?" translate="no">​</a></h2>
<p>With regular Git branches, you're confined to working in a single directory. When you want to switch between branches, you need to <code>git checkout</code> or <code>git switch</code>, which means saving or stashing your current work, switching the entire working directory to the new branch, and then resuming work. This context switching can be disruptive, especially when you're juggling multiple tasks or need to quickly reference code from another branch.</p>
<p>Git worktrees eliminate this friction by giving each branch its own physical directory. You can have your main branch running in one terminal tab, a feature branch in another, and a hotfix branch in a third - all simultaneously.</p>
<p>Each directory maintains its own state: uncommitted changes, running processes, and even different dependency installations if needed. This separation makes multitasking not just possible, but actually pleasant.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-now-a-decade-after-release">Why now (a decade after release)?<a href="https://yakov.dev/the-moment-for-git-worktrees#why-now-a-decade-after-release" class="hash-link" aria-label="Direct link to Why now (a decade after release)?" title="Direct link to Why now (a decade after release)?" translate="no">​</a></h2>
<p>Until a few weeks ago, I wasn't aware this command even existed in Git. I had stumbled upon my own "hack" - cloning the same repository multiple times with different branches to work on several tasks simultaneously. When I shared this approach with a colleague, he said, "Oh, you should check out worktrees. It might be a better fit for this use case."</p>
<p>That's when I discovered that Git has had this feature since 2015, but it somehow flew under my (and most developers) radar. Intrigued, I decided to spend a week experimenting with worktrees to see if they could replace my cloning approach.</p>
<p>During this trial period, I set up three different worktrees for my current project: one for a major feature I was developing, another for urgent bug fixes that kept coming up, and a third for some technical debt cleanup that I'd been putting off. The setup was surprisingly smooth, and I found myself naturally gravitating toward using different terminal windows for different worktrees.</p>
<p>What struck me most during this experiment was how the mental model changed. Instead of thinking "I need to switch branches," I started thinking "I need to switch contexts" - and each context had its own physical space. This subtle shift made multitasking feel less chaotic and more intentional.</p>
<p>The timing of my discovery wasn't coincidental though. The rise of AI coding assistants like Claude Code (Anthropic's AI-powered development environment) and Cursor (an AI-first code editor) has fundamentally changed how we approach development work. These tools have made worktrees not just convenient, but genuinely effective.</p>
<p>Here's where it gets interesting: AI agents (autonomous AI systems that can write, modify, and test code independently) excel at handling isolated, well-defined tasks. When you point Claude Code at a specific worktree with a clear objective, it can work autonomously without the mental overhead of context switching that plagues human developers. This combination of physical isolation (separate directories) and logical isolation (focused tasks) creates an ideal environment for AI-assisted development.</p>
<p>Through experimentation, I've identified three main use cases where worktrees truly shine:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="long-running-side-tasks">Long-running Side Tasks<a href="https://yakov.dev/the-moment-for-git-worktrees#long-running-side-tasks" class="hash-link" aria-label="Direct link to Long-running Side Tasks" title="Direct link to Long-running Side Tasks" translate="no">​</a></h3>
<p>Perfect for dependency updates, documentation improvements, or refactoring tasks that you want to chip away at over time without disrupting your main development flow. I keep a dedicated worktree for these maintenance tasks, allowing me to make progress on them during natural breaks in feature development.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="environment-experimentation">Environment Experimentation<a href="https://yakov.dev/the-moment-for-git-worktrees#environment-experimentation" class="hash-link" aria-label="Direct link to Environment Experimentation" title="Direct link to Environment Experimentation" translate="no">​</a></h3>
<p>Need to test with a different Node version? Want to try a new dependency without breaking your current setup and having to reinstall node_modules? Worktrees let you maintain completely isolated environments while keeping everything in the same repository. This is particularly valuable when you need to compare performance or behavior across different configurations.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-agent-parallel-work">AI Agent Parallel Work<a href="https://yakov.dev/the-moment-for-git-worktrees#ai-agent-parallel-work" class="hash-link" aria-label="Direct link to AI Agent Parallel Work" title="Direct link to AI Agent Parallel Work" translate="no">​</a></h3>
<p>This is where worktrees truly excel in 2025. Each AI agent gets its own sandbox to work in, reducing the cognitive overhead of task switching and making it easier to review and integrate changes systematically. I found myself setting up different worktrees for different types of tasks:</p>
<ul>
<li class="">One worktree for the main feature branch where I need more focus and precision</li>
<li class="">Another for some bugfix that needed to be done quickly</li>
<li class="">A third for refactoring legacy code</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="current-limitations-and-future-potential">Current Limitations and Future Potential<a href="https://yakov.dev/the-moment-for-git-worktrees#current-limitations-and-future-potential" class="hash-link" aria-label="Direct link to Current Limitations and Future Potential" title="Direct link to Current Limitations and Future Potential" translate="no">​</a></h2>
<p>While experimenting with this approach, I initially thought I'd discovered an unbeatable hack - multiple unrelated tasks running simultaneously, with me just orchestrating from above. My backlog would be cleaned out in a day!</p>
<p>However, after about a week of testing, I discovered some realistic limitations. For production code, the real bottleneck often becomes code review capacity. Every line entering your codebase still needs to be understood and validated, and AI-generated code sometimes requires even more careful review than human-written code.</p>
<p>You can spin up as many worktrees as you want and assign AI agents to each one, but eventually all their work flows through your review process. This mirrors the same scaling challenge we've always had with teams: adding more developers doesn't automatically increase output if review capacity doesn't scale with it.</p>
<p>Context switching between worktrees also remains a challenge. While the technical barriers are removed, the mental overhead of juggling multiple tasks simultaneously is still very real.</p>
<p>That said, even with these limitations, I've found worktrees provide a meaningful productivity boost for certain types of work. The key is understanding when and how to use them effectively, rather than expecting them to be a silver bullet.</p>
<p>Despite these realistic constraints, my experience over the past few weeks has convinced me that worktrees represent something significant for modern development workflows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://yakov.dev/the-moment-for-git-worktrees#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>Git worktrees have become an essential part of my development workflow, not because they're revolutionary, but because they solve a very specific modern problem: how to manage multiple concurrent development streams in the age of AI assistance.</p>
<p>The beauty of git worktrees isn't in their technical complexity - they're actually quite simple. It's in their timing. They've been quietly waiting for a decade for the right use case to make them indispensable. With AI coding assistants becoming our collaborative partners rather than just tools, worktrees have found their moment.</p>
<p>Sometimes the best features are the ones that have been there all along, just waiting for the right context to make them essential. While git worktrees won't make you deliver 10 times faster, they might make you 2-3 times more efficient, and that's a meaningful boost that would have been hard to imagine just a few years back.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="resources">Resources<a href="https://yakov.dev/the-moment-for-git-worktrees#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://git-scm.com/docs/git-worktree" target="_blank" rel="noopener noreferrer" class="">Git Worktrees - Git Documentation</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=2uEqYw-N8uE" target="_blank" rel="noopener noreferrer" class="">thePrimagen discovers Git Worktrees</a></li>
<li class=""><a href="https://frontendmasters.com/courses/everything-git/worktrees/" target="_blank" rel="noopener noreferrer" class="">Frontend Masters - Git Course (needs signup)</a></li>
</ul>]]></content:encoded>
            <category>git</category>
            <category>development</category>
            <category>workflow</category>
            <category>productivity</category>
            <category>ai</category>
            <category>automation</category>
            <category>2025</category>
        </item>
        <item>
            <title><![CDATA[Test-Driven Development (TDD) with React: Complete Guide with Examples]]></title>
            <link>https://yakov.dev/tdd-with-react</link>
            <guid>https://yakov.dev/tdd-with-react</guid>
            <pubDate>Thu, 28 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn Test-Driven Development with React using Vitest and Testing Library. Step-by-step guide with real examples, best practices, and common pitfalls.]]></description>
            <content:encoded><![CDATA[<div class="container_ag6H"><span class="textWrapper_Mwbw"><p>Photo by <a href="https://www.pexels.com/@jan-van-der-wolf-11680885/">Jan van der Wolf</a> from <a href="https://www.pexels.com/photo/blue-and-yellow-road-sign-8824203/">Pexels</a></p></span></div>
<p><img decoding="async" loading="lazy" alt="image" src="https://yakov.dev/assets/images/pexels-photo-8824203-ac49babea3b20d4e832162bab6c1d7b6.jpeg" width="1024" height="683" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="prerequisites">Prerequisites<a href="https://yakov.dev/tdd-with-react#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites" translate="no">​</a></h2>
<p>Before diving into TDD with React, you should be familiar with:</p>
<ul>
<li class="">Basic React concepts (components, state, props)</li>
<li class="">JavaScript/TypeScript fundamentals</li>
<li class="">Command line basics</li>
<li class="">Basic understanding of testing concepts</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-test-driven-development">What is Test-driven development?<a href="https://yakov.dev/tdd-with-react#what-is-test-driven-development" class="hash-link" aria-label="Direct link to What is Test-driven development?" title="Direct link to What is Test-driven development?" translate="no">​</a></h2>
<blockquote>
<p>Test-driven development (TDD) is a software development process relying on software requirements being converted
to test cases before software is fully developed, and tracking all software development by repeatedly testing the
software against all test cases. This is as opposed to software being developed first and test cases created later.</p>
</blockquote>
<p><em>From <a href="https://en.wikipedia.org/wiki/Test-driven_development#Test-driven_development_cycle" target="_blank" rel="noopener noreferrer" class="">wikipedia</a></em></p>
<p>So what does it actually mean?
Instead of writing the code first and then adding tests to validate the added behavior, we first write the test and only then implement the new behavior.</p>
<p>Basically it should look something like this:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tdd-diagram">TDD Diagram<a href="https://yakov.dev/tdd-with-react#tdd-diagram" class="hash-link" aria-label="Direct link to TDD Diagram" title="Direct link to TDD Diagram" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="test driven development diagram showing red-green-refactor cycle" src="https://yakov.dev/assets/images/tdd-diagram-increment-e46c3c2a41cd2d1a9fd6dcd2dffaa00c.png" width="3025" height="2052" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-just-do-it-the-other-way-around">Why not just do it the other way around?<a href="https://yakov.dev/tdd-with-react#why-not-just-do-it-the-other-way-around" class="hash-link" aria-label="Direct link to Why not just do it the other way around?" title="Direct link to Why not just do it the other way around?" translate="no">​</a></h3>
<p>TDD requires the developer to change the way they approach the problem. When starting to practice it, it might seem unintuitive and the concept might take some time to grasp.
When implementation comes first, we're biased - TDD avoids this by starting with a failing test.
When starting with a failing test we know for sure that it's not yet operational, only when the test switches to green do we know we've reached our goal.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how">How?<a href="https://yakov.dev/tdd-with-react#how" class="hash-link" aria-label="Direct link to How?" title="Direct link to How?" translate="no">​</a></h2>
<p>In theory it sounds pretty nice and simple, let's see how we can actually do it.
We'll use React.js for the examples but the concepts are transferable to all other frameworks and libraries.
Our test runner will be <a href="https://vitest.dev/" target="_blank" rel="noopener noreferrer" class="">Vitest</a> and the rendering will be done by <a href="https://testing-library.com/docs/react-testing-library/intro" target="_blank" rel="noopener noreferrer" class="">Testing Library</a>
I chose Vite for this demo because it's fast, modern, and integrates smoothly with Vitest.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation--setup">Installation &amp; Setup<a href="https://yakov.dev/tdd-with-react#installation--setup" class="hash-link" aria-label="Direct link to Installation &amp; Setup" title="Direct link to Installation &amp; Setup" translate="no">​</a></h3>
<p>First of all let's get started with this command</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm create vite@latest my-app -- --template react-ts</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cd my-app</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm install</span><br></div></code></pre></div></div>
<p>Once it's finished we need to set up our testing environment. Let's install the necessary testing dependencies:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install --save-dev vitest @testing-library/react @testing-library/dom @types/react @types/react-dom jsdom</span><br></div></code></pre></div></div>
<p>Add a <code>vitest.config.ts</code> file to the root of the project with the following content:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">vitest.config.ts</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> defineConfig </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vitest/config'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> react </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@vitejs/plugin-react'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// https://vite.dev/config/</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">defineConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  plugins</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token function" style="color:#d73a49">react</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  test</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    environment</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'jsdom'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>Add test scripts to your <code>package.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">package.json</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"scripts"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"test"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"vitest"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-our-first-spec-file">Create Our First Spec File<a href="https://yakov.dev/tdd-with-react#create-our-first-spec-file" class="hash-link" aria-label="Direct link to Create Our First Spec File" title="Direct link to Create Our First Spec File" translate="no">​</a></h3>
<p>For now let's just create a simple spec file to make sure everything is working as expected.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.spec.ts</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> describe</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> expect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> it </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vitest'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">describe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'AppComponent'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">it</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should return true'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="run-the-tests">Run the Tests<a href="https://yakov.dev/tdd-with-react#run-the-tests" class="hash-link" aria-label="Direct link to Run the Tests" title="Direct link to Run the Tests" translate="no">​</a></h3>
<p>Let's run the test command <code>npm run test</code>. Vitest runs in watch mode by default, so each file change in the src directory will trigger a re-run of the test command.</p>
<p>You should see something like this:
<img decoding="async" loading="lazy" alt="vitest initial test run showing passing test" src="https://yakov.dev/assets/images/dummy-spec-121b4386dfb9dc265440f46c44a2a46b.png" width="726" height="169" class="img_ev3q"></p>
<p>Awesome, everything is working as expected!
We are ready to start our TDD journey. 🥳</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-task-requirement">New Task Requirement<a href="https://yakov.dev/tdd-with-react#new-task-requirement" class="hash-link" aria-label="Direct link to New Task Requirement" title="Direct link to New Task Requirement" translate="no">​</a></h3>
<p>Let's assume that we were assigned to develop a simple counter display, with "Increment", "Decrement" and "Reset" functionality.
We even got a prototype video of the feature:
<img decoding="async" loading="lazy" alt="counter app demo showing increment decrement and reset functionality" src="https://yakov.dev/assets/images/output-4c271fd3eb6f741a32aaf065cb3250c2.gif" width="536" height="462" class="img_ev3q"></p>
<p>Let's break that down into smaller blocks of logic:</p>
<ul>
<li class="">Increment<!-- -->
<ul>
<li class="">Button with "Increment" label should be displayed</li>
<li class="">Clicking the button should increment the count by one</li>
</ul>
</li>
<li class="">Decrement<!-- -->
<ul>
<li class="">Button with "Decrement" label should be displayed</li>
<li class="">Clicking the button should decrement the count by one</li>
</ul>
</li>
<li class="">Reset<!-- -->
<ul>
<li class="">Button with "Reset" label should be displayed</li>
<li class="">Clicking the button should set the count to 0</li>
</ul>
</li>
<li class="">Counter<!-- -->
<ul>
<li class="">Should be initialized with 0 as value</li>
</ul>
</li>
</ul>
<p>Basically we can use this as a reference to our TDD cycles. If we take increment click functionality and cast it on the <a href="https://yakov.dev/tdd-with-react#tdd-diagram" class="">diagram</a> we saw before it should look something like this:
<img decoding="async" loading="lazy" alt="test driven development diagram" src="https://yakov.dev/assets/images/tdd-diagram-increment-e46c3c2a41cd2d1a9fd6dcd2dffaa00c.png" width="3025" height="2052" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1st-test---increment-button-should-exist">1st Test - Increment Button Should Exist<a href="https://yakov.dev/tdd-with-react#1st-test---increment-button-should-exist" class="hash-link" aria-label="Direct link to 1st Test - Increment Button Should Exist" title="Direct link to 1st Test - Increment Button Should Exist" translate="no">​</a></h3>
<p>First of all let's clear the existing <code>App.tsx</code> file so it will return an empty <code>div</code> element:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App.css'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The first test should check if the button is rendered in the document, using Vitest's global <code>describe</code>, <code>test</code> and <code>expect</code> functions,
Testing Library's <code>render</code> function that renders the elements in the DOM (well, not an actual DOM, but that's a topic for another article),
and [<code>screen</code>] object which represents the document object in which the <code>render</code> function rendered. For a deeper understanding of this, I would suggest reading the official docs of <a href="https://vitest.dev/" target="_blank" rel="noopener noreferrer" class="">Vitest</a> and <a href="https://testing-library.com/" target="_blank" rel="noopener noreferrer" class="">Testing Library</a>.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.test.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> describe</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> expect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> test </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vitest'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">App</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> render</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> screen </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@testing-library/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">describe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'when app is rendered'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should display "increment" button'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Increment'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>This will be the output for the test:</p>
<p><img decoding="async" loading="lazy" alt="failed test showing increment button not found error" src="https://yakov.dev/assets/images/failed-test-001-790d07f1885308c2cfbe039258cb4714.png" width="1031" height="730" class="img_ev3q"></p>
<p>Let's go over what happened here. Since the button element wasn't implemented yet, <code>getByText</code> function couldn't find it in the DOM.</p>
<p>Since we didn't implement the button in the code, the test is failing. Now let's add the button:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports">logo</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./logo.svg'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App.css'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain-text">            Increment</span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Now the test would pass, as the target element is found</p>
<p><img decoding="async" loading="lazy" alt="passed test showing increment button successfully found" src="https://yakov.dev/assets/images/passed-test-001-e3e87deeb3382de56701f19ab9ad38b6.png" width="523" height="209" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2nd-test---click-on-button-should-increment-counter">2nd Test - Click on Button Should Increment Counter<a href="https://yakov.dev/tdd-with-react#2nd-test---click-on-button-should-increment-counter" class="hash-link" aria-label="Direct link to 2nd Test - Click on Button Should Increment Counter" title="Direct link to 2nd Test - Click on Button Should Increment Counter" translate="no">​</a></h3>
<p>The next step in our test flow should be "when user clicks on increment, counter should be incremented by one", but before we do that, we should test that the default count value is 0.</p>
<p>So let's add the following test:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.test.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> describe</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> expect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> test</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> beforeEach </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vitest'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">App</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> cleanup</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> render</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> screen </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@testing-library/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">describe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'when app is rendered'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">beforeEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">cleanup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should display "increment" button'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Increment'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should initiate counter with 0'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Count is 0'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<p>After this second test fails, we can add this logic:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App.css'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Increment</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Count is </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Now the test should pass.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3rd-test---click-on-increment-button-should-increment-counter">3rd Test - Click on Increment Button Should Increment Counter<a href="https://yakov.dev/tdd-with-react#3rd-test---click-on-increment-button-should-increment-counter" class="hash-link" aria-label="Direct link to 3rd Test - Click on Increment Button Should Increment Counter" title="Direct link to 3rd Test - Click on Increment Button Should Increment Counter" translate="no">​</a></h3>
<p>Now let's test the actual increment functionality. We need to test that when the user clicks the increment button, the counter value increases by 1,
We'll use <a href="https://testing-library.com/docs/user-event/intro/" target="_blank" rel="noopener noreferrer" class="">user-event</a> library to simulate user interactions.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.test.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> describe</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> expect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> test</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> beforeEach </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vitest'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">App</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> cleanup</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> render</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> screen </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@testing-library/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> userEvent  </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@testing-library/user-event'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">describe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'when app is rendered'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">beforeEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">cleanup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should display "increment" button'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Increment'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should initiate counter with 0'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Count is 0'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">test</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'should increment counter when increment button is clicked'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> userEvent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">click</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Increment'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">screen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getByText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Count is 1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toBeDefined</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>This test will fail because we haven't implemented the click handler yet. Let's add the functionality:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/App.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./App.css'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setCount</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">setCount</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f">count</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> count </span><span class="token tag script language-javascript operator" style="color:#393A34">+</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript number" style="color:#36acaa">1</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Increment</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Count is </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><br></div></code></pre></div></div>
<p>Now all tests should pass! We've successfully implemented the increment functionality using TDD.
Now you can follow the same pattern to implement the Decrement and Reset functionalities,
but remember to always start with a failing test first, and then make it pass.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="benefits-of-tdd-in-practice">Benefits of TDD in Practice<a href="https://yakov.dev/tdd-with-react#benefits-of-tdd-in-practice" class="hash-link" aria-label="Direct link to Benefits of TDD in Practice" title="Direct link to Benefits of TDD in Practice" translate="no">​</a></h2>
<p>Through this example, we can see several key benefits of TDD:</p>
<ul>
<li class=""><strong>Avoiding Uncovered Cases</strong>: By writing tests first, we ensure that all edge cases are considered and tested, when we write the code first we might miss some edge cases.</li>
<li class=""><strong>Avoiding False Positives</strong>: By writing the test first, we avoid the risk of writing code that appears to work but doesn't actually meet the requirements</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="faq">FAQ<a href="https://yakov.dev/tdd-with-react#faq" class="hash-link" aria-label="Direct link to FAQ" title="Direct link to FAQ" translate="no">​</a></h2>
<p><strong>Q: What's the difference between unit tests and integration tests in the context of TDD?</strong><br>
<!-- -->A: Unit tests focus on individual components or functions in isolation, while integration tests verify that multiple components work together correctly. TDD typically starts with unit tests and progresses to integration tests.</p>
<p><strong>Q: Is TDD slower than traditional development?</strong><br>
<!-- -->A: Initially, TDD might feel slower, but it often saves time in the long run by catching bugs early, reducing debugging time, and making refactoring safer.</p>
<p><strong>Q: Can I use TDD with existing codebases?</strong><br>
<!-- -->A: Yes! You can start applying TDD to new features or when refactoring existing code. You don't need to rewrite everything to benefit from TDD principles.</p>
<p><strong>Q: What about testing UI components? Isn't that brittle?</strong><br>
<!-- -->A: When testing UI components, focus on user behavior rather than implementation details. Use semantic queries (like <code>getByRole</code>, <code>getByLabelText</code>) instead of brittle selectors, and test what the user would actually do.</p>
<p><strong>Q: When is TDD not the most efficient approach?</strong><br>
<!-- -->A: TDD works best for well-defined, stable requirements. It may not be ideal for rapid prototyping, exploratory programming, or when requirements are constantly changing. In these cases, you might start with a prototype first, then add tests as the feature stabilizes. TDD also requires more upfront investment, so for very small scripts or one-off utilities, the overhead might not be worth it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://yakov.dev/tdd-with-react#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>Test-Driven Development is more than just a testing strategy - it's a design methodology that helps you build more reliable, maintainable software. By writing tests first, you're forced to think about your API design, error cases, and user requirements before diving into implementation.</p>
<p>The counter example we built demonstrates the core TDD cycle: Red (write a failing test), Green (make it pass with minimal code), and Refactor (improve the code while keeping tests green - we didn't focus on it as much). This approach ensures that every line of code you write has a clear purpose and is thoroughly tested.</p>
<p>While TDD may feel slower initially, the benefits compound over time. Once a good infrastructure is in place, you'll spend less time debugging, have more confidence when refactoring, and create better-designed code. The tests serve as both specification and safety net, making your codebase more robust and maintainable.</p>
<p>Start small with TDD—pick one new feature or bug fix and apply the Red-Green-Refactor cycle. As you become more comfortable with the process, you'll find that TDD becomes a natural part of your development workflow.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ready-to-start-tdd">Ready to Start TDD?<a href="https://yakov.dev/tdd-with-react#ready-to-start-tdd" class="hash-link" aria-label="Direct link to Ready to Start TDD?" title="Direct link to Ready to Start TDD?" translate="no">​</a></h2>
<p>Try implementing the decrement and reset functionality using the same TDD approach we covered. Remember: Red → Green → Refactor!</p>
<p>The key to mastering TDD is practice. Start with small features and gradually work your way up to more complex functionality. The investment in writing tests first pays off with more reliable, maintainable code.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="references">References<a href="https://yakov.dev/tdd-with-react#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://en.wikipedia.org/wiki/Test-driven_development#Test-driven_development_cycle" target="_blank" rel="noopener noreferrer" class="">Test-driven development - Wikipedia</a></li>
<li class=""><a href="https://vitejs.dev/guide/" target="_blank" rel="noopener noreferrer" class="">Vite - Getting Started</a></li>
<li class=""><a href="https://vitest.dev/" target="_blank" rel="noopener noreferrer" class="">Vitest Documentation</a></li>
<li class=""><a href="https://testing-library.com/docs/react-testing-library/intro" target="_blank" rel="noopener noreferrer" class="">React Testing Library Documentation</a></li>
</ul>]]></content:encoded>
            <category>blog</category>
            <category>react</category>
            <category>testing</category>
            <category>tdd</category>
            <category>vitest</category>
            <category>javascript</category>
            <category>typescript</category>
            <category>testing-library</category>
        </item>
        <item>
            <title><![CDATA[Bookmarklets - Bookmarks on steroids]]></title>
            <link>https://yakov.dev/bookmarklets-bookmarks-on-steroids</link>
            <guid>https://yakov.dev/bookmarklets-bookmarks-on-steroids</guid>
            <pubDate>Tue, 20 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Discover how JavaScript can supercharge your browser bookmarks.]]></description>
            <content:encoded><![CDATA[<div class="container_ag6H"><span class="textWrapper_Mwbw"><p>Photo by <a href="https://unsplash.com/@olia?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Olia 💙💛 Gozha</a> on <a href="https://unsplash.com/photos/J4kK8b9Fgj8?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p></span></div>
<p><img decoding="async" loading="lazy" alt="image" src="https://yakov.dev/assets/images/olia-gozha-J4kK8b9Fgj8-unsplash-212dc2e1c238fae33195f8c06c3ac389.jpg" width="1920" height="1275" class="img_ev3q"></p>
<blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tldr-bookmarklets-are-bookmarks-charged-with-the-power-of-javascript-they-let-you-execute-javascript-code-by-clicking-on-a-bookmark">tl;dr: Bookmarklets are bookmarks charged with the power of JavaScript. They let you execute JavaScript code by clicking on a bookmark.<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#tldr-bookmarklets-are-bookmarks-charged-with-the-power-of-javascript-they-let-you-execute-javascript-code-by-clicking-on-a-bookmark" class="hash-link" aria-label="Direct link to tl;dr: Bookmarklets are bookmarks charged with the power of JavaScript. They let you execute JavaScript code by clicking on a bookmark." title="Direct link to tl;dr: Bookmarklets are bookmarks charged with the power of JavaScript. They let you execute JavaScript code by clicking on a bookmark." translate="no">​</a></h3>
</blockquote>
<p>Ever found yourself repeatedly copying a particular text, navigating to a specific webpage,
or performing some other routine task while browsing? Bookmarklets are a neat trick that
can help you automate these mundane tasks. Instead of using a URL, these supercharged
bookmarks leverage JavaScript to perform complex tasks at the click of a button.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>warning</div><div class="admonitionContent_BuS1"><p>Before we proceed, it's important to understand the security implications of bookmarklets.
They involve running JavaScript code directly in your browser. Be wary of using bookmarklets
from sources you don't trust, as they can potentially expose your browser and data to security risks.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-do-bookmarklets-work">How do Bookmarklets work?<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#how-do-bookmarklets-work" class="hash-link" aria-label="Direct link to How do Bookmarklets work?" title="Direct link to How do Bookmarklets work?" translate="no">​</a></h2>
<p>Creating a bookmarklet is similar to creating a bookmark. The difference is that instead of inserting a
URL, you add JavaScript code. Whenever you click on the bookmarklet, this JavaScript code is executed.
It's a powerful feature that can automate a plethora of tasks that you perform in your browser.
Any JavaScript code that you can run in the browser console, you can run in a bookmarklet.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Make sure to prefix your JavaScript code with <code>javascript:</code> when creating a bookmarklet.
This tells the browser that it's not a standard URL.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="copy-a-frequently-used-string-to-the-clipboard">Copy a frequently used string to the clipboard<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#copy-a-frequently-used-string-to-the-clipboard" class="hash-link" aria-label="Direct link to Copy a frequently used string to the clipboard" title="Direct link to Copy a frequently used string to the clipboard" translate="no">​</a></h3>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token literal-property property" style="color:#36acaa">javascript</span><span class="token operator" style="color:#393A34">:</span><span class="token dom variable" style="color:#36acaa">navigator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">clipboard</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">writeText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'ce34839b-5eca-4ab5-86ac-02cc8ba76c8e'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fetch-data-from-an-api">Fetch data from an api<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#fetch-data-from-an-api" class="hash-link" aria-label="Direct link to Fetch data from an api" title="Direct link to Fetch data from an api" translate="no">​</a></h3>
<p>we can also use this to fetch data from an api, and display it in the console.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token literal-property property" style="color:#36acaa">javascript</span><span class="token operator" style="color:#393A34">:</span><span class="token function" style="color:#d73a49">fetch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'https://jsonplaceholder.typicode.com/todos/1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>As you can see, the code is one-liner. This is because bookmarklets don't support multi-line code.
Take in mind that you can use the <code>;</code> to separate multiple statements.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="expanding-your-bookmarklet-library">Expanding Your Bookmarklet Library<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#expanding-your-bookmarklet-library" class="hash-link" aria-label="Direct link to Expanding Your Bookmarklet Library" title="Direct link to Expanding Your Bookmarklet Library" translate="no">​</a></h3>
<p>The power of bookmarklets is limited only by your imagination.
You can automate numerous tasks that you frequently perform on your browser.
For more ideas and inspiration, check out these repositories:</p>
<p><a href="https://github.com/Krazete/bookmarklets" target="_blank" rel="noopener noreferrer" class="">https://github.com/Krazete/bookmarklets</a></p>
<p><a href="https://github.com/marcobiedermann/awesome-bookmarklets" target="_blank" rel="noopener noreferrer" class="">https://github.com/marcobiedermann/awesome-bookmarklets</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://yakov.dev/bookmarklets-bookmarks-on-steroids#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>Bookmarklets offer a way to harness the power of JavaScript to automate your browser
tasks and enhance your productivity. They're easy to create and can be as simple or
complex as you need them to be. But, like all powerful tools, they need to be used with caution.
So, remember to use or create bookmarklets from trusted sources to keep your browsing safe.</p>]]></content:encoded>
            <category>browser</category>
            <category>javascript</category>
            <category>bookmark</category>
            <category>bookmarklet</category>
            <category>2023</category>
        </item>
        <item>
            <title><![CDATA[Recursion in React simplified]]></title>
            <link>https://yakov.dev/recursion-in-react-simplified</link>
            <guid>https://yakov.dev/recursion-in-react-simplified</guid>
            <pubDate>Wed, 02 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Understand how recursion works with examples in React]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Endless Stairs" src="https://yakov.dev/assets/images/photo-1542355554783-b612ff00383c-f6bf37a59fd71d6e37efc0681a8e1567.jpg" width="2670" height="1780" class="img_ev3q"></p>
<p>Recursion is a computer science practice where a function calls itself until it reaches an exit condition. Sound pretty simple, right?</p>
<p>I Used to struggle with recursive code; it was hard to grasp the notion of something calling (invoking) itself, and it felt too abstract. Usually, recursion is demonstrated with the Fibonacci sequence, binary search tree, or some other theoretical example, which could be tough to wrap your head around. I wondered where such practice would be helpful UI-wise. For example, a comment section where each comment can have a sub-comment which will have a sub-comment of its own, which will have a sub-comment of its own, well, you got the idea.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>First, let's write our comment component without recursion: the author name the comment's content.</p></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">Comment</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> author</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> content </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text">: </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Let's render a comment within a comment. It sounds pretty basic, right? We have to call the comment component inside its return statement.</p></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">Comment</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> author</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> content</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> subComment </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag attr-value" style="color:#e3116c">comment</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text">: </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Comment</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread" style="color:#00009f">subComment</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>What is wrong with the code above? It's not working! We get an error that says "Cannot read property 'author' of null".
We need the exit condition for this component. When do we want this component to stop rendering itself? If the comment object doesn't have a sub-comment would be the specific case.</p>
<p>We could do this in two ways:</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Solution 1:
if the author or content props are missing then exit:</p></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">Comment</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> author</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> content</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> subComment </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">author </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag attr-value" style="color:#e3116c">comment</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text">: </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Comment</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread" style="color:#00009f">subComment</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Solution 2:
if the sub-comment object is null:</p></div></div>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:#d73a49">Comment</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> author</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> content</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> subComment </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag attr-value" style="color:#e3116c">comment</span><span class="token tag attr-value punctuation" style="color:#393A34">'</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text">: </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">subComment </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Comment</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread" style="color:#00009f">subComment</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>In the first solution, we call the Comment function (component). When the condition is not met, we exit it, and in the second solution, we check for the condition before calling the function.</p>
<p>You can play with the code here: <a href="https://codesandbox.io/s/simple-react-recursion-ycrtbb" target="_blank" rel="noopener noreferrer" class="">https://codesandbox.io/s/simple-react-recursion-ycrtbb</a></p>
<p>Thanks for reading!</p>]]></content:encoded>
            <category>blog</category>
            <category>react</category>
            <category>recursion</category>
            <category>2022</category>
        </item>
        <item>
            <title><![CDATA[My Plans & Goals For 2021]]></title>
            <link>https://yakov.dev/my-plans-and-goals-for-2021</link>
            <guid>https://yakov.dev/my-plans-and-goals-for-2021</guid>
            <pubDate>Wed, 24 Feb 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[What I plan to learn and the goals I want to achieve this year]]></description>
            <content:encoded><![CDATA[<p>2020 was a busy and challenging year; due to covid and downsizing, I had lost my previous job, and after more than two years, I had to start looking for a new job while the unemployment rate was sky high, losing my job caught me unprepared. When I was looking for a new job, I soon realized that even though I was practicing pretty modern and cutting-edge technologies, I still had many knowledge gaps.
While searching for a new job, I learned a lot and caught up a bit, but I'm still not where I would like to be.
During this period, any time I came across something I didn't know and wanted to learn, I added this to an endless list that just kept getting longer and longer.
Thinking about where I see myself in a year and what knowledge I would like to possess, I refind the list while trying to be as efficient and realistic as possible at the same time.
I hope to return to this post in a year and see that I have accomplished (hopefully most of it).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="learn">Learn<a href="https://yakov.dev/my-plans-and-goals-for-2021#learn" class="hash-link" aria-label="Direct link to Learn" title="Direct link to Learn" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bundlers-webpackrollupparcalsnowpack">Bundlers: webpack,rollup,parcal,snowpack.<a href="https://yakov.dev/my-plans-and-goals-for-2021#bundlers-webpackrollupparcalsnowpack" class="hash-link" aria-label="Direct link to Bundlers: webpack,rollup,parcal,snowpack." title="Direct link to Bundlers: webpack,rollup,parcal,snowpack." translate="no">​</a></h3>
<p><strong>Why:</strong> when using options like create-react-app, you might not need that at all, but when you want the ability to custom and modify the build process, I find it necessary to understand these tools better. Most of the time, I had to tweak something, I just copy-pasted it without really understanding the full implications of what I was doing.
Since webpack is the most popular one, this is the one I'm going to focus mostly on. After mastering one of these tools, the others will become more approachable and easy to get on board.</p>
<p><strong>How</strong>: Reading the official docs, possibly watch a tutorial and dive deep into using it, try to avoid preconfigured builders like create-react-app, and try to write the webpack config from scratch. And most importantly, for any future project that I will start, I can try and configure the webpack by myself.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="testing-jestmochareact-testing-library-puppeteer-and-cypress">Testing: jest,mocha,react-testing-library, puppeteer and cypress<a href="https://yakov.dev/my-plans-and-goals-for-2021#testing-jestmochareact-testing-library-puppeteer-and-cypress" class="hash-link" aria-label="Direct link to Testing: jest,mocha,react-testing-library, puppeteer and cypress" title="Direct link to Testing: jest,mocha,react-testing-library, puppeteer and cypress" translate="no">​</a></h3>
<p><strong>Why:</strong> I have a confession. I have never written a test in my life, not even a simple unit test. While I understand the upside of writing tests, I never really needed to learn this paradigm. As I'm maturing as a developer and understanding those processes better, I see the value of using tests in any project. Even on my small and relatively simple projects, I stumble on regressions and errors I know could have been prevented if I had some test implemented.</p>
<p><strong>How:</strong> For starters, understand the difference between test types (unit test, e2e, etc.). What kind of tools to use for each, and finally start integrating tests in my existing projects, and obviously in new future projects.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="typescript">TypeScript<a href="https://yakov.dev/my-plans-and-goals-for-2021#typescript" class="hash-link" aria-label="Direct link to TypeScript" title="Direct link to TypeScript" translate="no">​</a></h3>
<p><strong>Why:</strong> Quite frankly, I want to learn TypeScript to read and understand the source code of external packages. It's that simple. The best documentation is the source code itself.</p>
<p>Also, the fact that TS is gaining popularity is significant, from a nice to have ability to an almost necessity in the last few years.</p>
<p><strong>How:</strong> You guessed it, implementing TS in my existing projects. No reason to get fancy here.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nodejs">NodeJS<a href="https://yakov.dev/my-plans-and-goals-for-2021#nodejs" class="hash-link" aria-label="Direct link to NodeJS" title="Direct link to NodeJS" translate="no">​</a></h3>
<p><strong>Why:</strong> When I need to write code that doesn't "live" in the browser, the obvious choice for a web developer is node.js. For developing backend servers, writing cloud functions, web scraping, and even IoT devices, Node.js is a powerful tool to have in your toolbelt.</p>
<p><strong>How:</strong> To be honest, with node.js, I'm cheating because I already started learning and using it, but I want to expand on using it. For a JavaScript developer, the transition is pretty smooth, even though you still have to understand a few key concepts and get used to not having the 'window' object.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="git">git<a href="https://yakov.dev/my-plans-and-goals-for-2021#git" class="hash-link" aria-label="Direct link to git" title="Direct link to git" translate="no">​</a></h3>
<p><strong>Why:</strong> Well, I know git, but I can't say I have in-depth knowledge, pull, push, checkout, really the basics. I want to master it to the point where I don't have to use the GUI, just the commands and the complicated ones.</p>
<p><strong>How:</strong> I plan to take the Frontend Masters Git In-Depth course and make the switch to use the terminal more heavily than the GUI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="goals">Goals:<a href="https://yakov.dev/my-plans-and-goals-for-2021#goals" class="hash-link" aria-label="Direct link to Goals:" title="Direct link to Goals:" translate="no">​</a></h2>
<p><strong>Codewars:</strong> Codewars is a website where you can practice coding problem skills and algorithms for those who don't know. Over the last year or so, I laid aside my progress. I'm currently kyu(level) 6. I believe I can reach level 4 by the end of the year.</p>
<p><strong>yakov.dev: (my blog)</strong> I started this blog a few months ago. I want to keep it active, so at least one post per month will be a sufficient pace, although I hope to write even more.</p>
<p><strong>YDKJS (You Don't Know JS):</strong> I started this great series by Kyle Simpson a few months ago. I do plan to finish it sometime soon. When reading these books, I have encountered many complex concepts that make my understanding of the language much better. I recommend any web developer to read this series, I've learned a lot from it, and I only read the first two books out of 6.</p>
<p><strong>Mobile Development:</strong> I found myself in need of some functionality on my android phone that doesn't exist. After searching for an app, I decided to develop it myself.
It should be refreshing to try something new like Flutter for a small project and outside the JS ecosystem.</p>
<p><strong>Chrome &amp; Visual Studio Code extensions:</strong> I use Chrome and VS Code extensions daily, and it caught my interest in how those extensions developed and work under the hood. I'll start with one for each app.</p>
<p><strong>Continue Develop my Side Projects</strong> I have a few ongoing projects that I try to expand and add features all the time. Although I don't have a defined road map for them, I don't want to neglect them while focusing on the other goals I have set for this year.</p>
<h2></h2>
<p>To conclude, think about where you would like to be in a year, what skills you would like to have, and set goals for yourself. I believe that in our profession, you can't rest on your laurels, always thrive on getting better, and expand your knowledge.</p>
<p>See you next time! 🏆</p>]]></content:encoded>
            <category>goals</category>
            <category>plans</category>
            <category>2021</category>
        </item>
        <item>
            <title><![CDATA[New Home, New Beginnings]]></title>
            <link>https://yakov.dev/new-home-new-beginnings</link>
            <guid>https://yakov.dev/new-home-new-beginnings</guid>
            <pubDate>Tue, 08 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[First blog post at new website]]></description>
            <content:encoded><![CDATA[<p>Hi *,</p>
<p>Welcome to my new blog and my first post ever!</p>
<p>My Name is Yakov, a Frontend web developer from Haifa, Israel.</p>
<p>As a self-taught developer, I’ve stumbled across many topics, concepts, and disciplines that looked very intimidating and complicated at first. Still, after time and time again, they started to make sense. Subsequently, my confidence has grown, and step by step, I felt more comfortable learning new things.</p>
<p>One of the primary resources of information that helped me through were articles and blog posts, A lot of documentations are long and tedious, especially for a beginner developer, and sometimes a short blog post can simplify and explain some topics much better.</p>
<p>My main goal in starting this blog is to help others the same way others helped me. In this blog, I will write about software development ( mostly web-oriented ), career advice, insights, random tech stuff, and shawarma reviews.</p>
<p>Just kidding about the shawarma…or not…I haven’t decided yet.
Wish me luck and see you soon! 👋</p>]]></content:encoded>
            <category>blog</category>
            <category>personal</category>
            <category>career</category>
            <category>2020</category>
        </item>
    </channel>
</rss>