<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Emma Schmidt</title>
    <description>The latest articles on DEV Community by Emma Schmidt (@emma_schmidt_).</description>
    <link>https://dev.to/emma_schmidt_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3450005%2Fcd01195d-0cef-48c0-9d0b-8033f6246f7e.jpeg</url>
      <title>DEV Community: Emma Schmidt</title>
      <link>https://dev.to/emma_schmidt_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emma_schmidt_"/>
    <language>en</language>
    <item>
      <title>React.js Hooks: The Complete Practical Guide for Developers in 2026</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Fri, 08 May 2026 12:04:54 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/reactjs-hooks-the-complete-practical-guide-for-developers-in-2026-20di</link>
      <guid>https://dev.to/emma_schmidt_/reactjs-hooks-the-complete-practical-guide-for-developers-in-2026-20di</guid>
      <description>&lt;p&gt;If you want to write modern React applications and you want companies to&lt;br&gt;
&lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-reactjs-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire React.js developers&lt;/a&gt;&lt;/strong&gt; like you, then mastering Hooks is not optional&lt;br&gt;
anymore. Hooks are the foundation of every React codebase written after&lt;br&gt;
2019.They replaced class components, simplified state management, and&lt;br&gt;
made code reuse actually practical. This guide covers every major Hook&lt;br&gt;
with real working code, clear explanations, and common mistakes to avoid.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Are React Hooks?
&lt;/h2&gt;

&lt;p&gt;Hooks are functions that let you use React features like state and&lt;br&gt;
lifecycle inside regular function components. Before Hooks existed,&lt;br&gt;
you had to write class components to do any of that.&lt;/p&gt;

&lt;p&gt;Here is the same Counter component, written both ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old way using a Class Component:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Add
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Modern way using a Hook:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same result. Much less code. Far easier to read and test.&lt;/p&gt;




&lt;h2&gt;
  
  
  All the Hooks Covered in This Guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hook&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;useState&lt;/td&gt;
&lt;td&gt;Adds state to a component&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useEffect&lt;/td&gt;
&lt;td&gt;Runs side effects after render&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useContext&lt;/td&gt;
&lt;td&gt;Reads shared data without prop drilling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useRef&lt;/td&gt;
&lt;td&gt;Accesses DOM elements or stores mutable values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useMemo&lt;/td&gt;
&lt;td&gt;Caches expensive calculations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useCallback&lt;/td&gt;
&lt;td&gt;Caches a function reference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useReducer&lt;/td&gt;
&lt;td&gt;Manages complex state with actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Hooks&lt;/td&gt;
&lt;td&gt;Reuses logic across multiple components&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  1. useState
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; gives your component memory. It stores a value and&lt;br&gt;
triggers a re-render whenever that value changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real example with a todo list:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TodoApp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nf"&gt;setTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Type a task"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Most common mistake:&lt;/strong&gt; Mutating state directly instead of using the&lt;br&gt;
setter function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Wrong&lt;/span&gt;
&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Right&lt;/span&gt;
&lt;span class="nf"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. useEffect
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; runs code after the component renders. You use it for API&lt;br&gt;
calls, timers, subscriptions, and updating the document title.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// side effect code&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// cleanup code (optional)&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real example fetching users from an API:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How the dependency array controls when the effect runs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;           &lt;span class="c1"&gt;// Runs after every render&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;       &lt;span class="c1"&gt;// Runs once on mount only&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Runs when userId changes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real example with cleanup to prevent memory leaks:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always return a cleanup function when you set up timers,&lt;br&gt;
subscriptions, or event listeners.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. useContext
&lt;/h2&gt;

&lt;p&gt;Prop drilling means passing data through many layers of components&lt;br&gt;
just to reach the one that actually needs it. &lt;code&gt;useContext&lt;/code&gt; solves&lt;br&gt;
this by letting any component read shared data directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create the context and a provider:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ThemeContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Wrap your app:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.jsx&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Read the context from any component:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Navbar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#222&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Toggle Theme
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No props passed through intermediate components. The data is&lt;br&gt;
available anywhere inside the provider.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. useRef
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; has two distinct uses that are worth understanding separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use 1: Access a DOM element directly&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AutoFocusInput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"This auto-focuses"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use 2: Store a value that does not trigger a re-render&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;StopwatchApp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSeconds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervalRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setSeconds&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;seconds&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;s&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Start&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Stop&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference: changing a &lt;code&gt;useRef&lt;/code&gt; value does not cause the&lt;br&gt;
component to re-render. That is what makes it the right tool for&lt;br&gt;
storing timers and interval IDs.&lt;/p&gt;


&lt;h2&gt;
  
  
  5. useMemo
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; caches the result of an expensive calculation so it only&lt;br&gt;
runs again when its dependencies change, not on every render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;filteredProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; - &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The filter calculation only runs when &lt;code&gt;products&lt;/code&gt; or &lt;code&gt;filter&lt;/code&gt; changes,&lt;br&gt;
not when unrelated state changes cause a re-render.&lt;/p&gt;

&lt;p&gt;Do not add &lt;code&gt;useMemo&lt;/code&gt; everywhere. Only use it when you have measured&lt;br&gt;
a real performance issue. Adding it unnecessarily makes code harder&lt;br&gt;
to read for no actual benefit.&lt;/p&gt;


&lt;h2&gt;
  
  
  6. useCallback
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useCallback&lt;/code&gt; caches a function so that its reference stays the same&lt;br&gt;
between renders. This matters when you pass functions as props to&lt;br&gt;
components wrapped in &lt;code&gt;React.memo&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;memo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Button clicked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increment&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChildButton&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChildButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Child rendered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click Me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;useCallback&lt;/code&gt;, every re-render of &lt;code&gt;Parent&lt;/code&gt; creates a new&lt;br&gt;
function reference. &lt;code&gt;ChildButton&lt;/code&gt; would re-render every time even&lt;br&gt;
though nothing about it actually changed.&lt;/p&gt;


&lt;h2&gt;
  
  
  7. useReducer
&lt;/h2&gt;

&lt;p&gt;When state logic becomes complex, especially when one action needs&lt;br&gt;
to update multiple values at once, &lt;code&gt;useReducer&lt;/code&gt; is cleaner than&lt;br&gt;
multiple &lt;code&gt;useState&lt;/code&gt; calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INCREMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DECREMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_STEP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AdvancedCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; | Step: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DECREMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INCREMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reset&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_STEP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reducer function is a pure function that takes current state and&lt;br&gt;
an action, and returns the next state. This pattern makes complex&lt;br&gt;
state changes predictable and easy to test.&lt;/p&gt;


&lt;h2&gt;
  
  
  8. Custom Hooks
&lt;/h2&gt;

&lt;p&gt;This is where Hooks become truly powerful. A custom hook is a regular&lt;br&gt;
&lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/useful-javascript-tools-plugins?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt;&lt;/strong&gt; function whose name starts with &lt;code&gt;use&lt;/code&gt; and that calls other&lt;br&gt;
hooks inside it. You use custom hooks to extract and reuse logic across&lt;br&gt;
multiple components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Hook: useFetch&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Request failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using the custom hook in multiple components:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PostList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading posts...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Total users: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two different components. Same fetch logic. Zero code duplication.&lt;br&gt;
This is what makes custom hooks one of the most valuable patterns&lt;br&gt;
in React development.&lt;/p&gt;


&lt;h2&gt;
  
  
  Rules of Hooks
&lt;/h2&gt;

&lt;p&gt;These two rules are enforced by React and breaking them will cause bugs&lt;br&gt;
that are difficult to trace.&lt;br&gt;
Rule 1: Only call Hooks at the top level of a component.&lt;br&gt;
Never inside if statements, loops, or nested functions.&lt;br&gt;
Rule 2: Only call Hooks inside React function components&lt;br&gt;
or other custom hooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Bad&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isLoggedIn&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// breaks Rule 1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Right:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Good&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isLoggedIn&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// always at the top level&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;p&gt;useState       Store and update values, triggers re-render&lt;br&gt;
useEffect      Side effects: API calls, timers, subscriptions&lt;br&gt;
useContext     Read shared global data without prop drilling&lt;br&gt;
useRef         DOM access or persistent values without re-render&lt;br&gt;
useMemo        Cache expensive calculated values&lt;br&gt;
useCallback    Cache function references for child components&lt;br&gt;
useReducer     Complex state with multiple related values&lt;br&gt;
Custom Hook    Extract and reuse any logic across components&lt;/p&gt;




&lt;h2&gt;
  
  
  Projects to Build and Practice
&lt;/h2&gt;

&lt;p&gt;The fastest way to learn Hooks is to use them in real projects. Here&lt;br&gt;
are good starting points matched to the hooks they teach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Todo App: useState, useReducer&lt;/li&gt;
&lt;li&gt;Weather App: useEffect, custom useFetch hook&lt;/li&gt;
&lt;li&gt;Dark Mode Toggle: useContext, useState&lt;/li&gt;
&lt;li&gt;Search with Filter: useMemo, useState&lt;/li&gt;
&lt;li&gt;Click-outside Detector: useRef, useEffect&lt;/li&gt;
&lt;li&gt;Shopping Cart: useReducer, useContext combined&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick one, build it from scratch, and you will understand Hooks&lt;br&gt;
at a level that reading alone cannot give you.&lt;/p&gt;




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

&lt;p&gt;Most developers learn Hooks by memorizing the API. That approach works&lt;br&gt;
until something breaks and you cannot explain why. The better approach&lt;br&gt;
is to understand what each Hook is solving. useState solves the problem&lt;br&gt;
of memory inside a function. useEffect solves the problem of running&lt;br&gt;
code in response to changes. useRef solves the problem of holding a&lt;br&gt;
value without triggering a render.&lt;/p&gt;

&lt;p&gt;When you understand the problem each Hook exists to solve, picking the&lt;br&gt;
right one for any situation becomes straightforward.&lt;/p&gt;

&lt;p&gt;Start with useState and useEffect. Build something real. Add the other&lt;br&gt;
hooks only when you actually need them.&lt;/p&gt;




&lt;p&gt;Found this useful? Drop a reaction and follow for weekly React posts,&lt;br&gt;
project walkthroughs, and practical guides.&lt;/p&gt;




</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>You Are Using useEffect Wrong - 5 Common Mistakes and How to Fix Them (2026)</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Thu, 07 May 2026 08:54:30 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/you-are-using-useeffect-wrong-5-common-mistakes-and-how-to-fix-them-2026-2afg</link>
      <guid>https://dev.to/emma_schmidt_/you-are-using-useeffect-wrong-5-common-mistakes-and-how-to-fix-them-2026-2afg</guid>
      <description>&lt;p&gt;&lt;em&gt;If you have ever had a bug you could not explain, infinite loops, stale data, or memory leaks, useEffect was probably involved.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is one of the most used hooks in React. It is also one of the most misunderstood. Whether you are a solo developer leveling up your skills or a tech lead looking to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-reactjs-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire React.js Developers&lt;/a&gt;&lt;/strong&gt; who truly understand the framework, knowing how useEffect works under the hood is non-negotiable in 2026. Even experienced developers ship bugs caused by subtle useEffect mistakes every single day. In this post, we will walk through the 5 most common useEffect mistakes, show you exactly why they break your app, and give you the correct pattern to fix each one. By the end, you will have a much clearer mental model of how useEffect actually works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 1 - Missing the Cleanup Function
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You set up a subscription, a timer, or an event listener inside useEffect but never clean it up. This causes &lt;strong&gt;memory leaks&lt;/strong&gt; and bugs that are incredibly hard to trace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interval keeps running even after the component unmounts. In large apps, these leaks stack up and slow everything down.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Always return a cleanup function that tears down whatever you set up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Cleanup on unmount&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same pattern applies to event listeners, WebSocket connections, and API subscriptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Event listener cleanup&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If you set it up inside useEffect, clean it up in the return function.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 2 - Stale Closures in the Dependency Array
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You reference a variable inside useEffect but forget to add it to the dependency array. React captures the value at the time the effect runs, so you end up reading an old, stale value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Always prints 0 - stale closure!&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Always sets to 1, never increments correctly&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// count is missing from deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;count&lt;/code&gt; is frozen at &lt;code&gt;0&lt;/code&gt; inside the closure because it is never listed as a dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Option A - Add the dependency properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Option A&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option B - Use the functional updater form of setState (best for counters and toggling):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Option B (preferred for counters)&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// No dependency needed&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option B is cleaner because the effect does not need to re-run every time count changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 3 - Using an Object or Array as a Dependency
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Objects and arrays are compared &lt;strong&gt;by reference&lt;/strong&gt; in JavaScript, not by value. If you create an object or array inside the component and pass it as a dependency, React sees a new reference on every render and runs the effect endlessly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electronics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;inStock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// New object reference every render = infinite loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This triggers the effect on every single render, even when the values inside the object have not changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Option A - Use primitive values as dependencies instead of objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Option A&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electronics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inStock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inStock&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inStock&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Primitives compared by value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option B - Memoize the object with &lt;code&gt;useMemo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Option B&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electronics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inStock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// Stable reference&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Mistake 4 - Fetching Data Without Handling Race Conditions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You fetch data inside useEffect but the component re-renders (or unmounts) before the request completes. An older request finishes after a newer one and overwrites your state with stale data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/user/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Could be stale data from an old request&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user clicks quickly and &lt;code&gt;userId&lt;/code&gt; changes twice, the first slow request might resolve after the second one, setting the wrong user in state.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Use an &lt;code&gt;isCancelled&lt;/code&gt; flag or the &lt;code&gt;AbortController&lt;/code&gt; API to ignore outdated responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Using AbortController&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/user/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Ignore cancelled requests&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Cancel the request on cleanup&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Using isCancelled flag&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isCancelled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/user/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isCancelled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Only update if still relevant&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isCancelled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;AbortController&lt;/code&gt; approach is preferred in 2026 because it also cancels the network request itself, saving bandwidth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 5 - Putting Too Much Logic Inside useEffect
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Developers often dump complex logic directly into useEffect, making it hard to read, test, and reuse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG - useEffect doing too much&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/dashboard/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastVisit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dashboard_viewed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is three separate concerns crammed into one effect. It is untestable and will cause confusing bugs when any one piece changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Split each concern into its own useEffect or extract logic into a custom hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Separate effects for separate concerns&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;fetchDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setDashboard&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastVisit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dashboard_viewed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better, extract it into a custom hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CORRECT - Custom hook&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDashboard&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/dashboard/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setDashboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage in component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom hooks make your effects reusable, testable, and far easier to read.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference - All 5 Fixes at a Glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Root Cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Missing cleanup&lt;/td&gt;
&lt;td&gt;Resource leak on unmount&lt;/td&gt;
&lt;td&gt;Return a cleanup function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stale closure&lt;/td&gt;
&lt;td&gt;Missing dependency&lt;/td&gt;
&lt;td&gt;Add to deps or use functional updater&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object as dependency&lt;/td&gt;
&lt;td&gt;Reference comparison&lt;/td&gt;
&lt;td&gt;Use primitives or useMemo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Race conditions&lt;/td&gt;
&lt;td&gt;Async + re-render timing&lt;/td&gt;
&lt;td&gt;Use AbortController&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Too much in one effect&lt;/td&gt;
&lt;td&gt;Poor separation of concerns&lt;/td&gt;
&lt;td&gt;Split effects or use custom hooks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Bonus - The Two Questions to Ask Before Every useEffect
&lt;/h2&gt;

&lt;p&gt;Before you write any useEffect, ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Does this actually need to be an effect?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lot of things developers put in useEffect do not belong there. Derived state, event handlers, and one-time initializations often do not need useEffect at all. If you are transforming data from props or state, just compute it inline or use &lt;code&gt;useMemo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. What cleans this up?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you cannot answer this question, you probably have a memory leak waiting to happen. Always think cleanup first.&lt;/p&gt;




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

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is not complicated once you understand the mental model. Every mistake above comes down to the same root cause: not thinking carefully about &lt;strong&gt;when the effect runs&lt;/strong&gt;, &lt;strong&gt;what it depends on&lt;/strong&gt;, and &lt;strong&gt;what it leaves behind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Fix these five patterns in your codebase and you will eliminate a whole category of React bugs overnight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which of these mistakes have you made before?&lt;/strong&gt; Drop a comment below. I can guarantee everyone reading has hit at least three of them. And if this saved you some debugging time, a ❤️ helps other devs find this post.&lt;/p&gt;




</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Build Your Own AI Agent from Scratch Using Python + LangChain + OpenAI in 2026</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Thu, 07 May 2026 05:20:22 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/build-your-own-ai-agent-from-scratch-using-python-langchain-openai-in-2026-g74</link>
      <guid>https://dev.to/emma_schmidt_/build-your-own-ai-agent-from-scratch-using-python-langchain-openai-in-2026-g74</guid>
      <description>&lt;p&gt;&lt;em&gt;A step-by-step guide for developers who want to go beyond ChatGPT wrappers and build something real.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;AI agents are no longer a research concept. They are production tools being shipped by teams worldwide right now. Whether you are looking to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-python-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire Python developers&lt;/a&gt;&lt;/strong&gt; to build intelligent automation for your company, or you are a solo dev leveling up your own skills, understanding how to build an AI agent from scratch is one of the most valuable things you can learn in 2026. In this guide, we will build a fully functional AI agent using &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/what-is-langchain-ai-app-development?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;&lt;/strong&gt;, and the &lt;strong&gt;OpenAI API&lt;/strong&gt;. One that can reason, use tools, and complete multi-step tasks autonomously. No fluff. Just working code and clear explanations.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Exactly Is an AI Agent?
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code, let us get the definition right.&lt;/p&gt;

&lt;p&gt;A standard LLM call looks like this:&lt;br&gt;
User Input &amp;gt; LLM &amp;gt; Output&lt;/p&gt;

&lt;p&gt;An AI agent looks like this:&lt;br&gt;
User Input &amp;gt; LLM &amp;gt; Decision &amp;gt; Tool Use &amp;gt; Observe Result &amp;gt; LLM &amp;gt; Decision &amp;gt; Final Output&lt;/p&gt;

&lt;p&gt;The key difference is the &lt;strong&gt;loop&lt;/strong&gt;. An agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decide &lt;em&gt;which tool&lt;/em&gt; to use based on context&lt;/li&gt;
&lt;li&gt;Call that tool (search the web, run code, query a database)&lt;/li&gt;
&lt;li&gt;Observe the result&lt;/li&gt;
&lt;li&gt;Decide what to do next&lt;/li&gt;
&lt;li&gt;Repeat until it reaches a final answer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is called the &lt;strong&gt;ReAct pattern&lt;/strong&gt; (Reasoning + Acting), and it is the foundation of almost every modern AI agent framework.&lt;/p&gt;


&lt;h2&gt;
  
  
  What We Are Building
&lt;/h2&gt;

&lt;p&gt;By the end of this tutorial, you will have an &lt;strong&gt;&lt;a href="https://www.zignuts.com/ai-agent-development-services?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;AI agent&lt;/a&gt;&lt;/strong&gt; that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answer questions using &lt;strong&gt;web search&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Perform &lt;strong&gt;math calculations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Look up &lt;strong&gt;current weather&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Chain multiple tools together to solve complex tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All orchestrated automatically by LangChain + OpenAI. You just give it a goal in plain English.&lt;/p&gt;


&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;An OpenAI API key &lt;/li&gt;
&lt;li&gt;Basic familiarity with Python functions and pip&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Step 1 - Project Setup
&lt;/h2&gt;

&lt;p&gt;Create a clean project directory and set up a virtual environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;ai-agent-tutorial
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent-tutorial
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate  &lt;span class="c"&gt;# Windows: venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain langchain-openai langchain-community openai python-dotenv duckduckgo-search numexpr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in your project root:&lt;br&gt;
OPENAI_API_KEY=your_openai_api_key_here&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2 - Load Environment Variables
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;agent.py&lt;/code&gt; and start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;OPENAI_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never hardcode your API key. Always use &lt;code&gt;.env&lt;/code&gt; and add it to &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 - Initialize the LLM
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OPENAI_API_KEY&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We set &lt;code&gt;temperature=0&lt;/code&gt; because agents need &lt;strong&gt;deterministic, logical reasoning&lt;/strong&gt;, not creative text generation. Lower temperature = more consistent tool selection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 - Define the Tools
&lt;/h2&gt;

&lt;p&gt;Tools are just Python functions wrapped with a LangChain decorator. The agent reads the docstring to understand &lt;em&gt;what the tool does&lt;/em&gt; and &lt;em&gt;when to use it&lt;/em&gt;, so write clear docstrings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool 1 - Web Search
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DuckDuckGoSearchRun&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;

&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DuckDuckGoSearchRun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Search the web for current information.
    Use this when the user asks about recent events,
    news, or anything that requires up-to-date data.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tool 2 - Math Calculator
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Evaluate a mathematical expression.
    Use this for any arithmetic, algebra, or numeric calculation.
    Input must be a valid Python math expression as a string.
    Example: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(100 * 1.08) ** 2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__builtins__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}},&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error evaluating expression: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Security note:&lt;/strong&gt; The &lt;code&gt;eval()&lt;/code&gt; here is sandboxed with empty builtins. For production use, use the &lt;code&gt;numexpr&lt;/code&gt; library or a dedicated math parser instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tool 3 - Weather Lookup (Simulated)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Get the current weather for a city.
    Use this when the user asks about weather conditions
    in a specific location.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mock_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;london&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cloudy, 14°C, 80% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new york&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sunny, 22°C, 55% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokyo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rainy, 18°C, 90% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mumbai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hot and humid, 34°C, 75% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Weather data not available for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 - Bundle the Tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain will pass this list to the agent, which learns what each tool does from the docstrings automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6 - Create the Agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentExecutor&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hwchase17/react&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;handle_parsing_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 7 - Run the Agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Who won the most recent FIFA World Cup and when was it held?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;✅ Answer:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If I invest $5,000 at 8% annual compound interest for 10 years, how much will I have?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;✅ Answer:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the current population of Japan? Now divide that by 1,000,000 and round it.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;✅ Answer:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 8 - Sample Output
&lt;/h2&gt;

&lt;p&gt;Entering new AgentExecutor chain...&lt;/p&gt;

&lt;p&gt;Thought: I need to find the current population of Japan.&lt;br&gt;
Action: web_search&lt;br&gt;
Action Input: current population of Japan 2026&lt;br&gt;
Observation: Japan's population is approximately 123.2 million as of 2026.&lt;br&gt;
Thought: Now I need to divide 123,200,000 by 1,000,000.&lt;br&gt;
Action: calculator&lt;br&gt;
Action Input: 123200000 / 1000000&lt;br&gt;
Observation: 123.2&lt;br&gt;
Thought: I now know the final answer.&lt;br&gt;
Final Answer: Japan's population is 123.2 million, which equals 123.2 when divided by 1,000,000.&lt;/p&gt;

&lt;p&gt;Finished chain.&lt;/p&gt;


&lt;h2&gt;
  
  
  Full &lt;code&gt;agent.py&lt;/code&gt; - Complete Code
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DuckDuckGoSearchRun&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentExecutor&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DuckDuckGoSearchRun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search the web for current information about recent events or news.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Evaluate a mathematical expression. Input must be a valid Python math expression.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__builtins__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}},&lt;/span&gt; &lt;span class="p"&gt;{}))&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get current weather for a city.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mock_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;london&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cloudy, 14°C, 80% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new york&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sunny, 22°C, 55% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokyo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rainy, 18°C, 90% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mumbai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hot and humid, 34°C, 75% humidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Weather data not available for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hwchase17/react&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;handle_parsing_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the weather in Tokyo and what is 34°C in Fahrenheit?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;✅ Answer:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Extend This Agent
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Add memory:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.memory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConversationBufferMemory&lt;/span&gt;

&lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConversationBufferMemory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add a custom database tool:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_user_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Look up user information from the internal database by user ID.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: Name=John, Plan=Pro, Joined=2026-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Swap to an open-source model:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.llms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vague tool docstrings&lt;/strong&gt; - the agent picks tools by reading them. Be specific or it hallucinates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;max_iterations&lt;/code&gt;&lt;/strong&gt; - a confused agent loops forever and drains your API credits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;temperature &amp;gt; 0&lt;/code&gt;&lt;/strong&gt; - makes tool selection unpredictable. Always use &lt;code&gt;0&lt;/code&gt; for agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skipping &lt;code&gt;handle_parsing_errors=True&lt;/code&gt;&lt;/strong&gt; - malformed output will crash silently without it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What to Build Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Research agent&lt;/strong&gt; - searches, summarises, and writes a report on any topic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code reviewer agent&lt;/strong&gt; - reads a GitHub PR and suggests improvements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer support agent&lt;/strong&gt; - handles tier-1 tickets using your product database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data analyst agent&lt;/strong&gt; - takes a CSV and answers plain-English questions about it&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;You have just built a working AI agent from scratch. One that reasons, selects tools, observes results, and loops until it finds the answer. This is not a toy demo. The same architecture powers production agents at companies shipping real products today.&lt;/p&gt;

&lt;p&gt;The concepts here, ReAct loops, tool definitions, memory, and executor configuration, transfer directly to more advanced frameworks like &lt;strong&gt;LangGraph&lt;/strong&gt;, &lt;strong&gt;AutoGen&lt;/strong&gt;, and &lt;strong&gt;CrewAI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What kind of agent are you going to build?&lt;/strong&gt; Drop it in the comments. I read every single one. And if this helped you, a ❤️ goes a long way in helping other devs find this post.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this useful? Follow me for more Python, AI, and backend deep dives every week.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>python</category>
      <category>ai</category>
      <category>langchain</category>
      <category>openai</category>
    </item>
    <item>
      <title>How to Hire Next.js Developers Who Actually Know App Router, Server Components and Edge Functions</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Wed, 06 May 2026 05:14:26 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/how-to-hire-nextjs-developers-who-actually-know-app-router-server-components-and-edge-functions-ipd</link>
      <guid>https://dev.to/emma_schmidt_/how-to-hire-nextjs-developers-who-actually-know-app-router-server-components-and-edge-functions-ipd</guid>
      <description>&lt;p&gt;When you decide to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-nextjs-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire Next.js Developers&lt;/a&gt;&lt;/strong&gt; for your product, you quickly realize that not all candidates are equal. The framework has evolved massively since the Pages Router days, and many developers still live in that old world. This guide cuts through the noise and gives you a precise, technical hiring framework to identify engineers who genuinely understand the App Router, &lt;strong&gt;&lt;a href="https://www.zignuts.com/question-and-answer/how-do-react-server-components-enhance-full-stack-application-performance-and-developer-experience?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;React Server Components (RSC)&lt;/a&gt;&lt;/strong&gt;, and Edge Functions, so you stop paying for developers who Google everything on the job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Knowledge Gap Is Wider Than You Think
&lt;/h2&gt;

&lt;p&gt;Next.js 13 and beyond introduced a mental model shift, not just a syntax change. The App Router is not simply a new file convention. It is a full rethinking of how data fetching, rendering, caching, and routing coexist in a React application.&lt;/p&gt;

&lt;p&gt;Developers who learned Next.js before 2023 are often fluent in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getServerSideProps&lt;/code&gt; / &lt;code&gt;getStaticProps&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pages under &lt;code&gt;/pages&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;API routes via &lt;code&gt;/pages/api&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Client-side data fetching with SWR or React Query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But modern Next.js (14 and 15) expects you to think in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server Components vs Client Components&lt;/li&gt;
&lt;li&gt;Layouts, Templates, and nested routing via &lt;code&gt;/app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Route Handlers instead of API routes&lt;/li&gt;
&lt;li&gt;Streaming with Suspense&lt;/li&gt;
&lt;li&gt;Edge and Node.js runtimes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding this gap helps you write better job descriptions and ask the right interview questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 1: App Router Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to Look For
&lt;/h3&gt;

&lt;p&gt;A strong candidate should be able to explain the &lt;code&gt;/app&lt;/code&gt; directory structure without hesitation and articulate why nested layouts exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interview Question to Ask
&lt;/h3&gt;

&lt;p&gt;"Walk me through how you would set up a dashboard with a shared sidebar that does not re-render on route changes, while each dashboard page fetches its own data server-side."&lt;/p&gt;

&lt;h3&gt;
  
  
  Expected Answer Pattern
&lt;/h3&gt;

&lt;p&gt;They should mention:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A root &lt;code&gt;layout.tsx&lt;/code&gt; that wraps all pages&lt;/li&gt;
&lt;li&gt;A nested &lt;code&gt;dashboard/layout.tsx&lt;/code&gt; that holds the sidebar as a Server Component&lt;/li&gt;
&lt;li&gt;Individual &lt;code&gt;page.tsx&lt;/code&gt; files for each dashboard route that fetch their own data using &lt;code&gt;async/await&lt;/code&gt; directly in the component&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code They Should Be Comfortable Writing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/dashboard/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/Sidebar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DashboardLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex h-screen"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sidebar&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 overflow-y-auto p-6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/dashboard/analytics/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnalyticsData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/analytics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AnalyticsPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getAnalyticsData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Analytics&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Total Users: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalUsers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A weak candidate will suggest using &lt;code&gt;useEffect&lt;/code&gt; for data fetching here or ask where to put &lt;code&gt;getServerSideProps&lt;/code&gt;. That is your signal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 2: React Server Components (RSC)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why This Is a Frequent Lie on Resumes
&lt;/h3&gt;

&lt;p&gt;Server Components are architecturally different from anything React developers were used to before. Many candidates claim to know them but cannot explain the boundary rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Boundary Rule Test
&lt;/h3&gt;

&lt;p&gt;Ask this directly: "What happens if you import a Client Component inside a Server Component and vice versa?"&lt;/p&gt;

&lt;p&gt;The correct answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Server Component &lt;strong&gt;can&lt;/strong&gt; import and render a Client Component.&lt;/li&gt;
&lt;li&gt;A Client Component &lt;strong&gt;cannot&lt;/strong&gt; import a Server Component. However, a Server Component can be passed as a &lt;code&gt;children&lt;/code&gt; prop to a Client Component.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code to Illustrate During the Interview
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/ProductCard.tsx  &amp;lt;-- Server Component (default)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AddToCartButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./AddToCartButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Client Component&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductCard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Direct DB or API call&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AddToCartButton&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/AddToCartButton.tsx  &amp;lt;-- Client Component&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AddToCartButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAdded&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setAdded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;added&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Added&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add to Cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask them: "Why does &lt;code&gt;AddToCartButton&lt;/code&gt; need &lt;code&gt;use client&lt;/code&gt;?" They should say: because it uses &lt;code&gt;useState&lt;/code&gt;, which is a browser-side hook that has no meaning on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus Question for Senior Candidates
&lt;/h3&gt;

&lt;p&gt;"How do Server Components affect bundle size?"&lt;/p&gt;

&lt;p&gt;Expected answer: Server Components are never sent to the client as JavaScript. The component runs on the server, returns serialized UI, and only the HTML output reaches the browser. This can dramatically reduce client-side JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 3: Edge Functions and the Runtime Model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Edge Functions Actually Are
&lt;/h3&gt;

&lt;p&gt;Edge Functions in Next.js run on a distributed runtime (like Cloudflare Workers or Vercel Edge Network) rather than a centralized Node.js server. They are closer to the user geographically and start up nearly instantly because they do not boot a full Node.js process.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Tradeoff Most Developers Miss
&lt;/h3&gt;

&lt;p&gt;Edge runtime does not support all Node.js APIs. Specifically, no &lt;code&gt;fs&lt;/code&gt;, no native modules, no long-running processes. Ask candidates about this explicitly.&lt;/p&gt;

&lt;p&gt;"Can you use the &lt;code&gt;fs&lt;/code&gt; module inside a Next.js middleware running on the Edge runtime?"&lt;/p&gt;

&lt;p&gt;Answer: No. The Edge runtime is a strict subset of the Web APIs. You need to use Web-standard APIs like &lt;code&gt;Request&lt;/code&gt;, &lt;code&gt;Response&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;crypto&lt;/code&gt;, and &lt;code&gt;Headers&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Edge Function Example: Auth Middleware
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth_token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Optionally decode JWT on the edge without Node crypto&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard/:path*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/account/:path*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strong candidates will note that JWT verification on the edge requires a Web Crypto-compatible library (like &lt;code&gt;jose&lt;/code&gt;) rather than &lt;code&gt;jsonwebtoken&lt;/code&gt;, which depends on Node.js internals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route Handler with Edge Runtime
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/geo/route.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;edge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;geo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 4: Caching and Revalidation
&lt;/h2&gt;

&lt;p&gt;This is where even experienced developers get tripped up. Next.js 14+ introduced a layered caching system that behaves differently from anything in the Pages Router.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four Cache Layers
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Request Memoization&lt;/strong&gt; - Within a single render tree, identical &lt;code&gt;fetch&lt;/code&gt; calls are deduped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Cache&lt;/strong&gt; - Persisted across requests and deployments, controlled by &lt;code&gt;next.revalidate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Route Cache&lt;/strong&gt; - Statically rendered routes cached at the CDN level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Router Cache&lt;/strong&gt; - Client-side cache of visited RSC payloads&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Interview Scenario
&lt;/h3&gt;

&lt;p&gt;"You have a product page that should update its price every 30 seconds but its description can stay cached for a week. How do you implement that?"&lt;/p&gt;

&lt;p&gt;Expected answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// For price (revalidate every 30s)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;priceData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/price/123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// For description (revalidate weekly)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;descData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/description/123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;604800&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use tag-based revalidation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fetching with a cache tag&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/products/123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// In a Server Action or Route Handler, revalidate by tag&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;revalidateTag&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/cache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;revalidateTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A weak candidate will suggest adding &lt;code&gt;cache: 'no-store'&lt;/code&gt; everywhere "to be safe." That is a performance anti-pattern that removes all caching benefits.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 5: Server Actions
&lt;/h2&gt;

&lt;p&gt;Server Actions are one of the most misunderstood modern features. They let you run server-side code directly from a form or event handler without writing a separate API route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example to Discuss
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/contact/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitContactForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveToDatabase&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ContactPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submitContactForm&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Your name"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Your email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask: "What is the security implication of using a Server Action exposed to a form?"&lt;/p&gt;

&lt;p&gt;A senior candidate will bring up CSRF protection (Next.js handles this automatically for Server Actions), input validation on the server, and rate limiting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 6: Practical Hiring Checklist
&lt;/h2&gt;

&lt;p&gt;Use this table when evaluating candidates after a technical screen.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill Area&lt;/th&gt;
&lt;th&gt;Junior&lt;/th&gt;
&lt;th&gt;Mid-Level&lt;/th&gt;
&lt;th&gt;Senior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App Router file conventions&lt;/td&gt;
&lt;td&gt;Knows basics&lt;/td&gt;
&lt;td&gt;Confident with parallel/intercepted routes&lt;/td&gt;
&lt;td&gt;Can architect complex nested layouts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server vs Client Components&lt;/td&gt;
&lt;td&gt;Knows the &lt;code&gt;use client&lt;/code&gt; directive&lt;/td&gt;
&lt;td&gt;Understands composition patterns&lt;/td&gt;
&lt;td&gt;Optimizes for minimal client bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data fetching&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;useEffect&lt;/code&gt; mostly&lt;/td&gt;
&lt;td&gt;Uses async Server Components&lt;/td&gt;
&lt;td&gt;Manages all four cache layers intentionally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge Functions&lt;/td&gt;
&lt;td&gt;Has heard of them&lt;/td&gt;
&lt;td&gt;Can write basic middleware&lt;/td&gt;
&lt;td&gt;Knows runtime limitations and tradeoffs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server Actions&lt;/td&gt;
&lt;td&gt;Unfamiliar&lt;/td&gt;
&lt;td&gt;Can implement basic forms&lt;/td&gt;
&lt;td&gt;Handles optimistic updates and error states&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;No awareness&lt;/td&gt;
&lt;td&gt;Uses Lighthouse&lt;/td&gt;
&lt;td&gt;Analyzes bundle, streaming, and TTFB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Section 7: Red Flags During Interviews
&lt;/h2&gt;

&lt;p&gt;Watch for these patterns. They are consistent signals of a developer who has not kept pace with the framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red flag 1:&lt;/strong&gt; They describe data fetching as "you have to use &lt;code&gt;getServerSideProps&lt;/code&gt; or fetch on the client." This tells you they are not using the App Router at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red flag 2:&lt;/strong&gt; They cannot explain why you would choose Node.js runtime over Edge runtime for a specific route. They treat edge as simply "faster" without understanding the constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red flag 3:&lt;/strong&gt; They add &lt;code&gt;"use client"&lt;/code&gt; to every component "just in case." This completely defeats the purpose of Server Components and bloats the client bundle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red flag 4:&lt;/strong&gt; They have no opinion on streaming. A developer working with modern Next.js should know about &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; boundaries and how they affect time to first byte.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red flag 5:&lt;/strong&gt; They cannot explain the difference between a Route Handler and a Server Action and when to use each.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 8: What a Good Technical Assessment Looks Like
&lt;/h2&gt;

&lt;p&gt;Rather than whiteboard problems, give candidates a small real-world task:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task brief (take-home, 3 to 4 hours):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a product listing page using the Next.js App Router that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetches products from a mock API at build time with ISR (revalidate every 60 seconds)&lt;/li&gt;
&lt;li&gt;Has a client-side search filter that does not trigger a server round trip&lt;/li&gt;
&lt;li&gt;Includes a "Add to Wishlist" Server Action that saves to a local JSON file or in-memory store&lt;/li&gt;
&lt;li&gt;Has a middleware that logs each request to the console only in development mode&lt;/li&gt;
&lt;li&gt;Has at least one route on the Edge runtime&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This task reveals everything. You see their folder structure, their understanding of the client/server boundary, their cache strategy, and how they think about the Edge runtime.&lt;/p&gt;




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

&lt;p&gt;The difference between a developer who knows Next.js and one who truly understands the modern stack is not about years of experience. It is about whether they have shipped real features using the App Router, wrestled with caching bugs, optimized Server Component boundaries, and deployed something to the edge.&lt;/p&gt;

&lt;p&gt;Your hiring process should reflect that reality. Ask about tradeoffs, not just syntax. Ask about production problems, not just toy examples. Ask them to write code that reveals their mental model of the server/client boundary.&lt;/p&gt;

&lt;p&gt;When you hire developers with this level of fluency, your Next.js application becomes faster, cheaper to run, and far easier to scale. When you do not, you end up with a codebase that looks like it uses the App Router but behaves like the Pages Router in disguise.&lt;/p&gt;




</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>hiring</category>
    </item>
    <item>
      <title>FastAPI vs Django vs Flask in 2026</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Tue, 05 May 2026 06:07:13 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/-g38</link>
      <guid>https://dev.to/emma_schmidt_/-g38</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9" class="crayons-story__hidden-navigation-link"&gt;FastAPI vs Django vs Flask in 2026: Choosing the Right Stack When You Hire Python Developers&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/emma_schmidt_" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3450005%2Fcd01195d-0cef-48c0-9d0b-8033f6246f7e.jpeg" alt="emma_schmidt_ profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/emma_schmidt_" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Emma Schmidt
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Emma Schmidt
                
              
              &lt;div id="story-author-preview-content-3612736" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/emma_schmidt_" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3450005%2Fcd01195d-0cef-48c0-9d0b-8033f6246f7e.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Emma Schmidt&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 5&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9" id="article-link-3612736"&gt;
          FastAPI vs Django vs Flask in 2026: Choosing the Right Stack When You Hire Python Developers
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/fastapi"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;fastapi&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/django"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;django&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/flask"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;flask&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>FastAPI vs Django vs Flask in 2026: Choosing the Right Stack When You Hire Python Developers</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Tue, 05 May 2026 06:05:58 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9</link>
      <guid>https://dev.to/emma_schmidt_/fastapi-vs-django-vs-flask-in-2026-choosing-the-right-stack-when-you-hire-python-developers-30p9</guid>
      <description>&lt;p&gt;Whether you are a startup founder, a product manager, or a CTO planning your next build, the framework decision shapes everything from developer productivity to runtime performance. When companies decide to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-python-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire Python developers&lt;/a&gt;&lt;/strong&gt;, one of the first architectural questions on the table is always the same: &lt;strong&gt;&lt;a href="https://www.zignuts.com/fastapi-development-company?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt;&lt;/strong&gt;, Django, or Flask? All three are alive, actively maintained, and used in production at scale in 2026, but they solve very different problems. This guide cuts through the noise with real code, real benchmark context, and a clear decision framework so you walk away knowing exactly which stack fits your situation.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Mental Model Before the Code
&lt;/h2&gt;

&lt;p&gt;Think of the three frameworks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/django?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Django&lt;/a&gt;&lt;/strong&gt; is a furnished apartment. Everything is included: ORM, admin panel, auth, forms, migrations. You move in and start living.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flask&lt;/strong&gt; is an empty flat. Four walls, great bones. You source every piece of furniture yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; is a modern co-living space built for speed. Async-first, typed by default, and opinionated about API contracts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Hello World: The Starting Point
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# myapp/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Django&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# myapp/urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django requires a project scaffold (&lt;code&gt;django-admin startproject&lt;/code&gt;), an installed app, and URL routing wired in two places minimum. More ceremony, but you get a complete ecosystem in return.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Flask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flask is beautifully minimal. The entire app can live in one file. Perfect for microservices or simple REST endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  FastAPI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from FastAPI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FastAPI matches Flask's brevity but adds async support and automatic OpenAPI docs out of the box at &lt;code&gt;/docs&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Data Validation and Type Safety
&lt;/h2&gt;

&lt;p&gt;This is where FastAPI pulls ahead in API-first projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  FastAPI with Pydantic v2
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field_validator&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="nd"&gt;@field_validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;age_must_be_positive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age must be a positive integer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;

&lt;span class="n"&gt;fake_db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UserCreate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;new_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fake_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="n"&gt;fake_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FastAPI validates the request body, serializes the response, and documents both automatically. No extra libraries. No decorators. Just type hints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Django REST Framework Equivalent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# serializers.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCreateSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EmailField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIView&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework.response&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCreateView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APIView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserCreateSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validated_data&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_201_CREATED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_400_BAD_REQUEST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django REST Framework is robust but more verbose. The serializer and view are separate concerns, which is clean but slower to scaffold.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Database Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django ORM (The Gold Standard for Relational DBs)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auth.User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ordering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# query
&lt;/span&gt;&lt;span class="n"&gt;recent_articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;author__username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django's ORM handles migrations, relationships, and querysets with elegance. For data-heavy applications, it is the most complete solution in the Python world.&lt;/p&gt;

&lt;h3&gt;
  
  
  FastAPI with SQLAlchemy 2.x and Async
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# database.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.ext.asyncio&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_async_engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AsyncSession&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DeclarativeBase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessionmaker&lt;/span&gt;

&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql+asyncpg://user:password@localhost/dbname&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_async_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;AsyncSessionLocal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sessionmaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AsyncSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expire_on_commit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeclarativeBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mapped&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mapped_column&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.database&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;__tablename__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapped_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapped_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapped_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapped_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server_default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c1"&gt;# routers/articles.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.ext.asyncio&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncSession&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;..database&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncSessionLocal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;..models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;AsyncSessionLocal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;

&lt;span class="nd"&gt;@router.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/articles/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AsyncSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scalars&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FastAPI with async SQLAlchemy handles high-concurrency reads extremely well. The setup is more involved than Django's ORM, but the performance payoff is real for I/O-bound workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Authentication
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django Built-in Auth
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.decorators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;login_required&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;

&lt;span class="nd"&gt;@login_required&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Session auth, password hashing, user model, groups, permissions -- all built in. For traditional web apps, nothing beats it.&lt;/p&gt;

&lt;h3&gt;
  
  
  FastAPI JWT Auth
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordBearer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordRequestForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;jose&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JWTError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;passlib.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CryptContext&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="n"&gt;SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-secret-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;ALGORITHM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HS256&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;ACCESS_TOKEN_EXPIRE_MINUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

&lt;span class="n"&gt;pwd_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CryptContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schemes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bcrypt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;oauth2_scheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OAuth2PasswordBearer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;to_encode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;expire&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ACCESS_TOKEN_EXPIRE_MINUTES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;to_encode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_encode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ALGORITHM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_current_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oauth2_scheme&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;credentials_exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Could not validate credentials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;algorithms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ALGORITHM&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;credentials_exception&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;JWTError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;credentials_exception&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/me&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_current_user&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More code to write, but total control over the token strategy. Pairs perfectly with stateless microservices.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Background Tasks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django with Celery
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tasks.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;celery&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shared_task&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.mail&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;send_mail&lt;/span&gt;

&lt;span class="nd"&gt;@shared_task&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;send_mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thanks for signing up.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;from_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello@yourapp.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;recipient_list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.tasks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;send_welcome_email&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;send_welcome_email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FastAPI with BackgroundTasks (Lightweight)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BackgroundTasks&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_email_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sending email to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/register/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundTasks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;send_email_sync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For heavy distributed task queues, pair FastAPI with Celery or ARQ. The built-in &lt;code&gt;BackgroundTasks&lt;/code&gt; is great for quick fire-and-forget operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Performance in 2026
&lt;/h2&gt;

&lt;p&gt;Benchmarks vary by hardware and test design, but the general direction is consistent across community reports:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Requests/sec (approx, simple JSON)&lt;/th&gt;
&lt;th&gt;Async Support&lt;/th&gt;
&lt;th&gt;ASGI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;td&gt;35,000 - 55,000&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flask (sync)&lt;/td&gt;
&lt;td&gt;8,000 - 15,000&lt;/td&gt;
&lt;td&gt;Via extensions&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Django (sync)&lt;/td&gt;
&lt;td&gt;7,000 - 13,000&lt;/td&gt;
&lt;td&gt;Partial (ASGI mode)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Django (async views)&lt;/td&gt;
&lt;td&gt;18,000 - 28,000&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Django's async views have matured significantly in Django 4.x and 5.x, closing the gap with FastAPI for mixed workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Admin Panels and CMS Needs
&lt;/h2&gt;

&lt;p&gt;If your product needs a back-office admin interface, Django wins without a fight.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# admin.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;

&lt;span class="nd"&gt;@admin.register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;list_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;list_filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;search_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;date_hierarchy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three lines of configuration and you have a searchable, filterable, paginated admin interface. FastAPI and Flask require third-party solutions like &lt;code&gt;sqladmin&lt;/code&gt; or a fully custom frontend.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Project Structure at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  FastAPI Recommended Structure for Large Teams
&lt;/h3&gt;

&lt;p&gt;project/&lt;br&gt;
|-- app/&lt;br&gt;
|   |-- init.py&lt;br&gt;
|   |-- main.py&lt;br&gt;
|   |-- core/&lt;br&gt;
|   |   |-- config.py&lt;br&gt;
|   |   |-- security.py&lt;br&gt;
|   |-- api/&lt;br&gt;
|   |   |-- v1/&lt;br&gt;
|   |   |   |-- endpoints/&lt;br&gt;
|   |   |   |   |-- users.py&lt;br&gt;
|   |   |   |   |-- articles.py&lt;br&gt;
|   |   |   |-- router.py&lt;br&gt;
|   |-- models/&lt;br&gt;
|   |   |-- user.py&lt;br&gt;
|   |   |-- article.py&lt;br&gt;
|   |-- schemas/&lt;br&gt;
|   |   |-- user.py&lt;br&gt;
|   |   |-- article.py&lt;br&gt;
|   |-- services/&lt;br&gt;
|   |   |-- user_service.py&lt;br&gt;
|   |-- db/&lt;br&gt;
|   |   |-- session.py&lt;br&gt;
|   |   |-- base.py&lt;br&gt;
|-- tests/&lt;br&gt;
|-- alembic/&lt;br&gt;
|-- pyproject.toml&lt;br&gt;
|-- Dockerfile&lt;/p&gt;

&lt;h3&gt;
  
  
  Django Standard Structure
&lt;/h3&gt;

&lt;p&gt;project/&lt;br&gt;
|-- manage.py&lt;br&gt;
|-- config/&lt;br&gt;
|   |-- settings/&lt;br&gt;
|   |   |-- base.py&lt;br&gt;
|   |   |-- development.py&lt;br&gt;
|   |   |-- production.py&lt;br&gt;
|   |-- urls.py&lt;br&gt;
|   |-- wsgi.py&lt;br&gt;
|   |-- asgi.py&lt;br&gt;
|-- apps/&lt;br&gt;
|   |-- users/&lt;br&gt;
|   |   |-- models.py&lt;br&gt;
|   |   |-- views.py&lt;br&gt;
|   |   |-- serializers.py&lt;br&gt;
|   |   |-- admin.py&lt;br&gt;
|   |   |-- tests.py&lt;br&gt;
|   |-- articles/&lt;br&gt;
|-- requirements/&lt;br&gt;
|-- Dockerfile&lt;/p&gt;

&lt;p&gt;Both scale well. Django's structure is prescribed. FastAPI's is flexible but requires team discipline.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django Test Client
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleAPITest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_list_articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/articles/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertIsInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FastAPI with pytest and httpx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.asyncio&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_list_articles&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/articles/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flask with pytest
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TESTING&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Flask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three frameworks integrate cleanly with pytest. FastAPI's async testing requires &lt;code&gt;httpx&lt;/code&gt; and &lt;code&gt;pytest-asyncio&lt;/code&gt; but gives you full async coverage.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Docker Setup for All Three
&lt;/h2&gt;

&lt;h3&gt;
  
  
  FastAPI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pyproject.toml .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fastapi uvicorn[standard] sqlalchemy asyncpg alembic pydantic-settings

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Django
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;python manage.py collectstatic &lt;span class="nt"&gt;--noinput&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flask
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask gunicorn

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["gunicorn", "app:app", "--bind", "0.0.0.0:5000", "--workers", "4"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. The Decision Framework
&lt;/h2&gt;

&lt;p&gt;Use this table to make the call quickly:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Situation&lt;/th&gt;
&lt;th&gt;Best Pick&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Building a full-stack web app with admin&lt;/td&gt;
&lt;td&gt;Django&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Building a high-performance REST or GraphQL API&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Building a simple microservice or internal tool&lt;/td&gt;
&lt;td&gt;Flask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need built-in auth, ORM, migrations&lt;/td&gt;
&lt;td&gt;Django&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need async WebSocket support&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team is junior and needs batteries included&lt;/td&gt;
&lt;td&gt;Django&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team values explicit types and API contracts&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rapid prototyping with full flexibility&lt;/td&gt;
&lt;td&gt;Flask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML model serving or data science APIs&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce or content platform&lt;/td&gt;
&lt;td&gt;Django&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Verdict
&lt;/h2&gt;

&lt;p&gt;There is no universal winner. The right answer depends on what you are building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose &lt;strong&gt;Django&lt;/strong&gt; when your product is data-driven, needs an admin panel, or your team wants a complete, convention-heavy framework that handles the plumbing for you.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;FastAPI&lt;/strong&gt; when you are building APIs, care deeply about performance and type safety, or need async-first concurrency for real-time features.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Flask&lt;/strong&gt; when the problem is small, the team is experienced, and you want full control with minimal overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In 2026, FastAPI adoption has accelerated significantly in the API and ML-serving space, while Django remains the dominant choice for product companies building full-featured web platforms. Flask has found a comfortable niche in &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/set-up-a-microservice-using-node-js-and-react-js" rel="noopener noreferrer"&gt;microservices&lt;/a&gt;&lt;/strong&gt; and internal tooling.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Did this help you make a decision? Drop your use case in the comments and let the community weigh in.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>django</category>
      <category>flask</category>
    </item>
    <item>
      <title>Why Senior Engineers Prefer to Hire ReactJS Developers with AI Tooling Skills in 2026</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Mon, 04 May 2026 12:34:52 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/why-senior-engineers-prefer-to-hire-reactjs-developers-with-ai-tooling-skills-in-2026-3l2e</link>
      <guid>https://dev.to/emma_schmidt_/why-senior-engineers-prefer-to-hire-reactjs-developers-with-ai-tooling-skills-in-2026-3l2e</guid>
      <description>&lt;p&gt;If you're looking to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-reactjs-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;hire ReactJS developers&lt;/a&gt;&lt;/strong&gt; in 2026, one thing has become crystal clear across engineering teams at startups and enterprises alike AI tooling proficiency is no longer a "nice to have." It's a core hiring signal that senior engineers now filter for before a candidate even reaches the technical round.&lt;/p&gt;

&lt;p&gt;This post breaks down &lt;em&gt;why&lt;/em&gt; that shift happened, &lt;em&gt;what&lt;/em&gt; AI-augmented React development looks like in practice, and &lt;em&gt;how&lt;/em&gt; to identify those skills during hiring.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Shift: Why AI Tooling Became Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;Three years ago, the React hiring checklist looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/react-hooks-guide?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hooks&lt;/a&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;State management (Redux / Zustand) &lt;/li&gt;
&lt;li&gt;Performance optimization &lt;/li&gt;
&lt;li&gt;Testing (RTL / Jest) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In 2026, that list has a new top-line requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can this developer move at AI-augmented speed without shipping AI-generated garbage?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Senior engineers aren't just looking for React knowledge they're looking for developers who know &lt;em&gt;how to wield AI tools as a force multiplier&lt;/em&gt; while still writing reviewable, maintainable, production-grade code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "AI Tooling Skills" Actually Means for React Devs
&lt;/h2&gt;

&lt;p&gt;Let's be concrete. AI tooling skills in a React context means:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Prompt-Driven Component Scaffolding (with review discipline)
&lt;/h3&gt;

&lt;p&gt;A skilled developer uses tools like &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/how-to-use-github-copilot?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;Cursor&lt;/strong&gt;, or &lt;strong&gt;Claude&lt;/strong&gt; to scaffold components fast and knows exactly what to change before committing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Prompting for a reusable Modal component&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prompt: "Create a reusable Modal component in React with&lt;/span&gt;
&lt;span class="c1"&gt;// Tailwind CSS, accessible aria attributes, and a close-on-backdrop-click feature"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ModalProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onClose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Modal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ModalProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dialogRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;dialogRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fixed inset-0 z-50 flex items-center justify-center bg-black/50"&lt;/span&gt;
      &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClose&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dialog"&lt;/span&gt;
      &lt;span class="na"&gt;aria-modal&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;aria-labelledby&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dialogRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-white rounded-2xl p-6 max-w-md w-full shadow-xl"&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-lg font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
          &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClose&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-4 text-sm text-gray-500 hover:text-gray-800"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Close
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What a senior engineer checks here:&lt;/strong&gt; Is &lt;code&gt;aria-modal&lt;/code&gt; set correctly? Is focus trapped inside? Is the &lt;code&gt;stopPropagation&lt;/code&gt; on the inner div intentional and documented? An AI-fluent developer &lt;em&gt;knows&lt;/em&gt; to verify these thing not blindly ship the output.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. AI-Assisted Debugging with Context Injection
&lt;/h3&gt;

&lt;p&gt;Instead of pasting errors into ChatGPT and hoping for the best, skilled devs inject full context the component tree, the error boundary, the state shape into their prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Debugging a stale closure bug&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bug: counter never updates beyond 1 in the interval callback&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//  stale closure count is always 0&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// empty deps captures count at 0&lt;/span&gt;

&lt;span class="c1"&gt;// AI-suggested fix:&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//  functional update avoids stale closure&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer with strong AI tooling skills knows &lt;em&gt;how to frame&lt;/em&gt; the debug prompt to get this answer not just copy-paste the broken code and shrug at the output.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Generating and Maintaining Tests with AI
&lt;/h3&gt;

&lt;p&gt;AI-assisted test generation is one of the highest-leverage skills in 2026. The bottleneck is no longer &lt;em&gt;writing&lt;/em&gt; tests it's &lt;em&gt;knowing what to test&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Component under test&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter email"&lt;/span&gt;
        &lt;span class="na"&gt;data-testid&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-input"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// AI-generated test (reviewed and approved by developer)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fireEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calls onSubmit with the entered email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoginForm&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockSubmit&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A developer who can write a &lt;em&gt;precise prompt&lt;/em&gt; to generate this test and catch missing edge cases (empty input, invalid email format) ships quality faster than one who writes every test manually &lt;em&gt;and&lt;/em&gt; faster than one who just runs AI-generated tests blindly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  4. AI-Powered Code Review Prep
&lt;/h3&gt;

&lt;p&gt;Before opening a PR, strong devs now run their diff through an AI review pass catching logic gaps, accessibility issues, and dead code before a senior engineer sees it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example prompt pattern:&lt;/strong&gt;&lt;br&gt;
This habit alone reduces PR review cycles by ~40% on teams that have adopted it.&lt;/p&gt;


&lt;h3&gt;
  
  
  5. AI-Driven Documentation Generation
&lt;/h3&gt;

&lt;p&gt;Good devs use AI to generate JSDoc and inline comments &lt;em&gt;that actually explain intent, not syntax.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Displays a paginated list of users with real-time search filtering.
 *
 * @remarks
 * Uses debounced input to avoid excessive API calls during fast typing.
 * Falls back to a cached result set if the network request fails.
 *
 * @param initialUsers - Pre-fetched users for SSR hydration
 * @param pageSize - Number of users per page (default: 20)
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;initialUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;UserListProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of documentation doesn't happen when developers use AI thoughtlessly it happens when they prompt with intent.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Senior Engineers Actually Look for in Interviews
&lt;/h2&gt;

&lt;p&gt;Here's a table of signals senior engineers now use when evaluating React candidates in 2026:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What they ask&lt;/th&gt;
&lt;th&gt;Red flag&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI tool awareness&lt;/td&gt;
&lt;td&gt;"Walk me through how you used Copilot on your last project"&lt;/td&gt;
&lt;td&gt;"I don't use AI tools" or "I use it for everything"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review discipline&lt;/td&gt;
&lt;td&gt;"Show me a PR where you modified AI output significantly"&lt;/td&gt;
&lt;td&gt;No modifications  copy-paste commits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt quality&lt;/td&gt;
&lt;td&gt;Live prompt exercise during interview&lt;/td&gt;
&lt;td&gt;Vague prompts, no iteration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing mindset&lt;/td&gt;
&lt;td&gt;"What edge cases did AI miss in your last test suite?"&lt;/td&gt;
&lt;td&gt;"The AI wrote all my tests"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ownership&lt;/td&gt;
&lt;td&gt;"Explain every line in this component"&lt;/td&gt;
&lt;td&gt;Can't explain AI-generated code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Real-World Impact: Before vs. After AI Tooling Adoption
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Without AI Tooling&lt;/th&gt;
&lt;th&gt;With AI Tooling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time to scaffold a feature&lt;/td&gt;
&lt;td&gt;4–6 hours&lt;/td&gt;
&lt;td&gt;1–2 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR review cycles&lt;/td&gt;
&lt;td&gt;3–4 rounds&lt;/td&gt;
&lt;td&gt;1–2 rounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test coverage&lt;/td&gt;
&lt;td&gt;40–60%&lt;/td&gt;
&lt;td&gt;70–90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation completeness&lt;/td&gt;
&lt;td&gt;Sparse&lt;/td&gt;
&lt;td&gt;Consistent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Onboarding time for new devs&lt;/td&gt;
&lt;td&gt;2–3 weeks&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How to Hire for This Skill
&lt;/h2&gt;

&lt;p&gt;If you're a hiring manager or tech lead, here's a practical screener:&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Task: The AI-Augmented Build
&lt;/h3&gt;

&lt;p&gt;Give the candidate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Figma mockup of a simple dashboard widget&lt;/li&gt;
&lt;li&gt;Access to Cursor or Copilot&lt;/li&gt;
&lt;li&gt;45 minutes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What you're evaluating:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do they start with a clear component architecture prompt or just start typing?&lt;/li&gt;
&lt;li&gt;Do they review and refactor AI output?&lt;/li&gt;
&lt;li&gt;Do they write tests or ask AI to generate them with context?&lt;/li&gt;
&lt;li&gt;Can they explain every decision in the code  including the parts AI wrote?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The best candidates treat AI like a fast junior dev  they delegate, review, correct, and own the output.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Hiring ReactJS developers in 2026 without filtering for AI tooling skills is like hiring a driver who's never used GPS  they might know the roads, but they're leaving serious productivity on the table.&lt;/p&gt;

&lt;p&gt;The senior engineers who are reshaping hiring criteria aren't looking for developers who use AI &lt;em&gt;more&lt;/em&gt;. They're looking for developers who use AI &lt;em&gt;better&lt;/em&gt;  with discipline, context-awareness, and genuine ownership of the code that ships.&lt;/p&gt;

&lt;p&gt;That's the skill that separates a 10x developer from someone who just has a fast autocomplete.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Are you a React developer building AI tooling habits? Or a hiring manager revamping your technical screen? Drop your approach in the comments  I'd love to compare notes.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>react</category>
      <category>javascript</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Bridging Code and Color: How Developers Can Hire Graphic Designers to Fix Their "Engineer-UI" Syndrome</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Fri, 01 May 2026 13:37:02 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/bridging-code-and-color-how-developers-can-hire-graphic-designers-to-fix-their-engineer-ui-16g4</link>
      <guid>https://dev.to/emma_schmidt_/bridging-code-and-color-how-developers-can-hire-graphic-designers-to-fix-their-engineer-ui-16g4</guid>
      <description>&lt;p&gt;You write clean code. Your architecture is solid. Your APIs respond in milliseconds.&lt;br&gt;
But when someone opens your app for the first time, their face does &lt;em&gt;that thing&lt;/em&gt;.&lt;br&gt;
You know the one. The slight wince. The polite "it's... functional." If you have&lt;br&gt;
ever stared at your own UI and thought "why does this look like a government tax&lt;br&gt;
portal from 2009?", you are not alone and the smartest move you can make is to&lt;br&gt;
&lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-graphic-designer?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;hire graphic designers&lt;/a&gt;&lt;/strong&gt; who can translate your logic-first thinking into&lt;br&gt;
interfaces that people actually enjoy using.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is "Engineer-UI" Syndrome?
&lt;/h2&gt;

&lt;p&gt;Engineer-UI Syndrome is not an insult. It is a pattern. It shows up when the&lt;br&gt;
person building the interface is optimizing for correctness rather than&lt;br&gt;
experience. The symptoms are recognizable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every element is left-aligned because that is the default&lt;/li&gt;
&lt;li&gt;Font sizes differ by exactly 2px across the entire page&lt;/li&gt;
&lt;li&gt;Buttons are rectangles with no border-radius because &lt;code&gt;border-radius&lt;/code&gt; felt
unnecessary&lt;/li&gt;
&lt;li&gt;The color palette is &lt;code&gt;#000000&lt;/code&gt;, &lt;code&gt;#ffffff&lt;/code&gt;, and one shade of Bootstrap blue&lt;/li&gt;
&lt;li&gt;Spacing is inconsistent because padding was added "until it stopped looking
weird"&lt;/li&gt;
&lt;li&gt;Forms have 14 fields on one screen because all 14 fields &lt;em&gt;are&lt;/em&gt; required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is software that works perfectly and communicates nothing. Users do&lt;br&gt;
not trust it. They miss important actions. They abandon onboarding flows. They&lt;br&gt;
email support asking where the submit button is even though it is right there,&lt;br&gt;
grey on a slightly lighter grey background.&lt;/p&gt;

&lt;p&gt;This is not a failure of intelligence. It is a failure of tooling. Developers&lt;br&gt;
are trained to think in systems, constraints, and logic trees. Designers are&lt;br&gt;
trained to think in perception, emotion, and visual hierarchy. These are&lt;br&gt;
different cognitive toolkits, and expecting one person to be expert in both is&lt;br&gt;
like expecting your database administrator to also compose the company jingle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Developers Struggle With Visual Design
&lt;/h2&gt;

&lt;p&gt;Understanding the root cause helps you fix it faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional Thinking vs. Perceptual Thinking
&lt;/h3&gt;

&lt;p&gt;When a developer looks at a screen, they see component trees, state, and data&lt;br&gt;
flow. When a designer looks at the same screen, they see where the eye lands&lt;br&gt;
first, what feels clickable, and whether the spacing creates rhythm or anxiety.&lt;br&gt;
Neither view is wrong. Both are necessary. But when only one view is applied,&lt;br&gt;
the result is half a product.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "If It Works, It Is Done" Trap
&lt;/h3&gt;

&lt;p&gt;Developers have a natural definition of done: the feature works, tests pass,&lt;br&gt;
no console errors. Design does not have a binary done state. It has a spectrum&lt;br&gt;
from "users are confused" to "users feel delighted." That spectrum is invisible&lt;br&gt;
to someone who has never been trained to see it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision Fatigue Around Aesthetics
&lt;/h3&gt;

&lt;p&gt;Making visual decisions without a system is exhausting. Should this heading be&lt;br&gt;
24px or 28px? Should this button be teal or navy? Without a design system or a&lt;br&gt;
trained eye, every micro-decision feels arbitrary, so developers either defer to&lt;br&gt;
defaults or copy something that looks decent without understanding why it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Dunning-Kruger Valley of UI
&lt;/h3&gt;

&lt;p&gt;Many developers go through a phase where they think good UI is about adding&lt;br&gt;
more: more gradients, more shadows, more animations. Then they discover&lt;br&gt;
Dribbble and feel overwhelmed. Then they overcorrect into brutal minimalism.&lt;br&gt;
Professional designers skip this valley because they spent years studying visual&lt;br&gt;
communication before they ever opened Figma.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Graphic Designer Actually Brings to a Dev Team
&lt;/h2&gt;

&lt;p&gt;Before you hire, understand what you are actually getting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Hierarchy and Layout
&lt;/h3&gt;

&lt;p&gt;A designer knows how to guide the user's eye from the most important element to&lt;br&gt;
the least important one without using a single instruction. They do this through&lt;br&gt;
size, weight, contrast, whitespace, and position. This is not decoration. It is&lt;br&gt;
navigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Color Theory Applied to Products
&lt;/h3&gt;

&lt;p&gt;Color in product design is not about what looks pretty. It is about what signals&lt;br&gt;
action, what signals danger, what signals success, and what fades into the&lt;br&gt;
background so the important elements can breathe. A designer will build a color&lt;br&gt;
system with semantic meaning, not a random palette pulled from a mood board.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typography as Communication
&lt;/h3&gt;

&lt;p&gt;Choosing a typeface is not just picking a font that looks nice. It is selecting&lt;br&gt;
a voice. A designer will pair typefaces with intention, establish a type scale&lt;br&gt;
that creates rhythm across the product, and make sure line height and letter&lt;br&gt;
spacing are set for actual readability, not just visual taste.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Systems and Component Libraries
&lt;/h3&gt;

&lt;p&gt;A senior designer will not hand you 40 one-off screens. They will hand you a&lt;br&gt;
system: a set of base tokens (colors, spacing, type scales) that feed into&lt;br&gt;
components (buttons, inputs, cards) that feed into patterns (forms, tables,&lt;br&gt;
navigation) that feed into full layouts. When you build from that system, every&lt;br&gt;
new feature looks like it belongs.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Research and Usability Thinking
&lt;/h3&gt;

&lt;p&gt;Good designers do not just make things look better. They question whether the&lt;br&gt;
flow makes sense. They will ask why the user is seeing this screen at all, what&lt;br&gt;
they already know when they arrive, and what they need to feel confident enough&lt;br&gt;
to take the next step. This thinking makes products better, not just prettier.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Actually Hire Graphic Designers as a Developer
&lt;/h2&gt;

&lt;p&gt;This is where most developer-led teams get stuck. They know they need design&lt;br&gt;
help. They do not know how to evaluate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know the Difference Between Design Disciplines
&lt;/h3&gt;

&lt;p&gt;"Graphic designer" is a broad term. Here is a quick breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UI Designer&lt;/strong&gt;: Focuses on the visual interface layer. Colors, typography,
spacing, component design. This is usually what developer teams need first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UX Designer&lt;/strong&gt;: Focuses on the user journey, flows, and information
architecture. Essential for complex products.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand/Graphic Designer&lt;/strong&gt;: Focuses on identity, illustration, marketing
materials. Important but usually not the first hire for a product team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product Designer&lt;/strong&gt;: A hybrid who handles both UI and UX with product
thinking. Usually more expensive but extremely valuable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most developer-built products, a strong UI designer or product designer is&lt;br&gt;
the right first hire. If your flows are already solid but your visuals look like&lt;br&gt;
an internal tool that escaped into the wild, a UI designer is your answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to Look For in a Portfolio
&lt;/h3&gt;

&lt;p&gt;When you review a designer's portfolio, do not just look at whether it looks&lt;br&gt;
nice. Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this work look consistent across screens?&lt;/li&gt;
&lt;li&gt;Can I see evidence of a design system or component thinking?&lt;/li&gt;
&lt;li&gt;Does the hierarchy make sense? Do I know what to do on each screen without
being told?&lt;/li&gt;
&lt;li&gt;Is there context about the problem they were solving, not just the final
output?&lt;/li&gt;
&lt;li&gt;Have they worked on products with similar complexity to yours?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A portfolio full of landing pages may not prepare someone for the complexity of&lt;br&gt;
a data-heavy dashboard. A portfolio of mobile apps may not translate directly to&lt;br&gt;
a complex web application. Match the portfolio to your context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to Find Designers
&lt;/h3&gt;

&lt;p&gt;Depending on your budget and timeline, you have several options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Freelance Platforms&lt;/strong&gt;: Toptal, Contra, and Dribbble's job board tend to have&lt;br&gt;
higher-quality product designers than generalist platforms. Behance is also&lt;br&gt;
worth searching for portfolios directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Communities&lt;/strong&gt;: Layers, Designers Guild, and various Slack communities&lt;br&gt;
for product designers are places where strong designers actually hang out. A&lt;br&gt;
direct outreach to someone whose work you admire is often more effective than&lt;br&gt;
posting a job listing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;: Straightforward but competitive. Strong candidates get a lot of&lt;br&gt;
messages. Make your outreach specific. Reference their actual work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Agencies&lt;/strong&gt;: If you need a design system built from scratch quickly,&lt;br&gt;
engaging a small agency for a defined sprint can be more efficient than a long&lt;br&gt;
hiring process. You get a team, a process, and a deliverable in a defined window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referrals&lt;/strong&gt;: The most reliable signal. Ask other developers or founders who&lt;br&gt;
have hired designers for strong recommendations.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Write a Job Description That Attracts Good Designers
&lt;/h3&gt;

&lt;p&gt;Most developer-written design job descriptions repel good candidates because&lt;br&gt;
they read like engineering requirements. Avoid listing tools as requirements&lt;br&gt;
("must know Figma, Sketch, Adobe XD, Illustrator, Photoshop, After Effects")&lt;br&gt;
because tool fluency is not design skill. Instead, describe the problem you are&lt;br&gt;
trying to solve, the kind of product you are building, and what success looks&lt;br&gt;
like. Good designers want to understand the challenge, not recite their software&lt;br&gt;
licenses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interview Questions That Actually Reveal Design Thinking
&lt;/h3&gt;

&lt;p&gt;Skip "what is your design process?" It produces rehearsed answers. Instead, try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Walk me through a time when you pushed back on a product decision for design
reasons. What happened?"&lt;/li&gt;
&lt;li&gt;"If you looked at our product for 20 minutes, what would you want to fix first
and why?"&lt;/li&gt;
&lt;li&gt;"How do you decide when a design is done?"&lt;/li&gt;
&lt;li&gt;"Tell me about a constraint that made a design better."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions reveal how a designer thinks under pressure, how they&lt;br&gt;
communicate with non-designers, and whether they see design as decoration or&lt;br&gt;
strategy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making the Collaboration Actually Work
&lt;/h2&gt;

&lt;p&gt;Hiring a designer is step one. Making the collaboration productive is the harder&lt;br&gt;
part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give Designers Access to Real Constraints
&lt;/h3&gt;

&lt;p&gt;The worst design feedback a developer can give is "make it look better." The&lt;br&gt;
best is "this table needs to display between 2 and 200 rows, the user is usually&lt;br&gt;
on a 13-inch laptop, and they need to sort, filter, and export without leaving&lt;br&gt;
the screen." Real constraints produce better design. Share your technical&lt;br&gt;
boundaries early and often.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stop Pixel-Pushing, Start System-Building
&lt;/h3&gt;

&lt;p&gt;If every design handoff is a static mockup that you translate directly into&lt;br&gt;
code, you are using design as decoration. Push for a design system. Invest the&lt;br&gt;
time to build shared tokens in your codebase that map to the designer's Figma&lt;br&gt;
variables. When you do this, new features stop being design emergencies and&lt;br&gt;
start being component assembly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Figma Dev Mode or Similar Handoff Tools
&lt;/h3&gt;

&lt;p&gt;Modern design tools have made the gap between design and code smaller than it&lt;br&gt;
has ever been. Figma's Dev Mode exposes CSS properties, spacing values, and&lt;br&gt;
component details directly to developers. Use it. Stop guessing at padding&lt;br&gt;
values from screenshots.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Shared Language
&lt;/h3&gt;

&lt;p&gt;Designers say "weight" and "hierarchy." Developers say "font-bold" and&lt;br&gt;
"z-index." Both are describing the same intentions in different vocabularies.&lt;br&gt;
Take the time to build a shared glossary. When a designer says "this needs more&lt;br&gt;
breathing room," know that they mean whitespace, which maps to padding or margin&lt;br&gt;
in your implementation. When you say "this is a controlled component," explain&lt;br&gt;
what that means for the designer's interaction model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ship Together, Not Sequentially
&lt;/h3&gt;

&lt;p&gt;The worst development process for design quality is: design hands off&lt;br&gt;
everything, development builds everything, then design reviews at the end when&lt;br&gt;
changing anything costs three sprints. Instead, design and develop in parallel&lt;br&gt;
with short loops. Design the first two flows. Build them. Review together. Adjust&lt;br&gt;
the system based on what was discovered in implementation. Then design the next&lt;br&gt;
two flows with that knowledge baked in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Red Flags When Hiring Designers
&lt;/h2&gt;

&lt;p&gt;Knowing what to avoid saves you significant pain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Designers who cannot explain their decisions&lt;/strong&gt;: If every choice is
"because it looks good," they do not have the vocabulary or depth to work
with a technical team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designers who have never shipped real products&lt;/strong&gt;: Dribbble shots are
controlled environments. Real products have edge cases, error states, empty
states, loading states, and small screens. A portfolio with only polished
hero screens is a warning sign.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designers who treat developer feedback as interference&lt;/strong&gt;: The best
designers want to know your constraints. They see technical limits as creative
challenges, not obstacles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designers who cannot work with existing systems&lt;/strong&gt;: Unless you are building
from scratch, your designer needs to work within or extend what exists, not
raze it. Someone who only wants to redesign everything from zero may not be
the right fit.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Practical Starting Point
&lt;/h2&gt;

&lt;p&gt;If you are a solo developer or a small team not ready to hire full-time, here is&lt;br&gt;
a realistic path forward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audit your current UI with fresh eyes&lt;/strong&gt;: Screenshot every main screen.&lt;br&gt;
Print them out or put them in a document. Look at them as a user who has&lt;br&gt;
never seen your product. Write down the three things that feel most broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fix the fundamentals first&lt;/strong&gt;: Before hiring anyone, apply a consistent&lt;br&gt;
type scale, a four or eight point spacing grid, and a limited color palette.&lt;br&gt;
These three changes alone will eliminate most of the "Engineer-UI" feel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hire a designer for a focused sprint&lt;/strong&gt;: Rather than a long engagement, hire&lt;br&gt;
a strong UI designer for a two to four week design sprint focused on your&lt;br&gt;
core flows. Ask for a component library at the end, not just screens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build from that system&lt;/strong&gt;: Use the component library as the foundation for&lt;br&gt;
all future development. Every new feature should start by asking "which&lt;br&gt;
existing components can I use?" before reaching for custom CSS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plan for ongoing design support&lt;/strong&gt;: As your product grows, your design needs&lt;br&gt;
will grow. Budget for regular design involvement, even if it is part-time or&lt;br&gt;
fractional.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Engineer-UI Syndrome is not a character flaw. It is a skills gap, and skills&lt;br&gt;
gaps have solutions. The developers who build products people love are not&lt;br&gt;
necessarily better engineers. They are engineers who understood early that&lt;br&gt;
building the right thing and making it feel right are two different disciplines&lt;br&gt;
that both deserve investment.&lt;/p&gt;

&lt;p&gt;When you hire graphic designers with product experience and build a real working&lt;br&gt;
relationship with them, you are not adding a cosmetic layer on top of your work.&lt;br&gt;
You are completing it. Your code gives the product its skeleton. Design gives it&lt;br&gt;
a face, a voice, and the kind of first impression that turns a curious visitor&lt;br&gt;
into a loyal user.&lt;/p&gt;

&lt;p&gt;The gap between "it works" and "it delights" is a collaboration problem.&lt;br&gt;
Hire for it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>From YAML to GenAI: How to Hire DevOps Engineers for the New Era of "Vibe Coding" and Automation</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Fri, 01 May 2026 13:16:39 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/from-yaml-to-genai-how-to-hire-devops-engineers-for-the-new-era-of-vibe-coding-and-automation-2h0n</link>
      <guid>https://dev.to/emma_schmidt_/from-yaml-to-genai-how-to-hire-devops-engineers-for-the-new-era-of-vibe-coding-and-automation-2h0n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: The DevOps Landscape Has Shifted
&lt;/h2&gt;

&lt;p&gt;The software industry is going through one of its most dramatic transformations in decades. When you decide to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-devops-engineers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;hire DevOps engineers&lt;/a&gt;&lt;/strong&gt; today, you are not just filling a role that manages pipelines and writes infrastructure scripts. You are bringing in someone who must operate at the intersection of traditional systems thinking, cloud-native architecture, and now, generative AI-powered development workflows. The old checklist of skills no longer cuts it. "&lt;a href="https://www.zignuts.com/blog/vibe-coding-failures-project-rescue?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Vibe coding&lt;/a&gt;," a term that has rapidly entered the developer zeitgeist, is reshaping how engineers interact with code, tools, and automation. Hiring managers, CTOs, and engineering leads who do not adapt their evaluation frameworks risk onboarding talent that is mismatched for where software delivery is actually heading.&lt;/p&gt;

&lt;p&gt;This guide breaks down everything you need to know about finding, evaluating, and retaining DevOps engineers who are built for this new era.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is "Vibe Coding" and Why Does It Matter for DevOps?
&lt;/h2&gt;

&lt;p&gt;"Vibe coding" refers to the increasingly common practice of using &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/llm-hallucinations-in-ai-models?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;large language models (LLMs)&lt;/a&gt;&lt;/strong&gt; and AI pair programmers to generate, refactor, and debug code through natural language prompts. Instead of writing every line manually, engineers describe what they want and iterate on AI-generated output. Tools like GitHub Copilot, Cursor, and various Claude-powered integrations have made this a daily reality for many development teams.&lt;/p&gt;

&lt;p&gt;For DevOps engineers, this shift is particularly significant. Infrastructure as Code (IaC), CI/CD pipelines, Kubernetes manifests, Helm charts, Ansible playbooks: all of these were already highly templated and pattern-driven. They are a natural fit for AI-assisted generation. A DevOps engineer who knows how to prompt an LLM to scaffold a Terraform module in seconds, then critically review and harden the output, is dramatically more productive than one who writes it from scratch every time.&lt;/p&gt;

&lt;p&gt;But this cuts both ways. The risk is that engineers who lean too heavily on AI-generated configurations without deeply understanding what the code does can introduce silent misconfigurations, security vulnerabilities, and brittle automation. The right DevOps hire for this era needs both fluency with AI tools and the foundational depth to audit their output.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Skill Shifts You Need to Understand
&lt;/h2&gt;

&lt;h3&gt;
  
  
  From Script Writing to Prompt Engineering and Code Review
&lt;/h3&gt;

&lt;p&gt;Traditionally, a strong DevOps candidate would demonstrate the ability to write complex Bash scripts, create reusable Ansible roles, or build parameterized Terraform modules from memory. That skill is still valuable, but the weight of evaluation has shifted.&lt;/p&gt;

&lt;p&gt;Today, the more important question is: can this engineer effectively direct AI tools and critically evaluate the output? Can they recognize when a Copilot-generated GitHub Actions workflow has a subtle permissions issue? Can they refactor an AI-generated Dockerfile that works but violates best practices for layer caching and security?&lt;/p&gt;

&lt;p&gt;Prompt engineering for infrastructure and automation tasks is now a legitimate technical skill. The best candidates will have developed a personal workflow around AI assistance that makes them faster without making them reckless.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Tool Expertise to Platform Thinking
&lt;/h3&gt;

&lt;p&gt;A few years ago, hiring for DevOps meant asking about specific tools: Jenkins vs. CircleCI, Puppet vs. Chef, Nagios vs. Datadog. While tool familiarity still matters, the more important capability is platform thinking.&lt;/p&gt;

&lt;p&gt;Modern DevOps engineers need to understand developer experience as a product. Internal developer platforms (IDPs), self-service infrastructure, golden paths: these concepts require engineers to think about their fellow developers as customers. This shift requires empathy, product intuition, and systems design skills that go well beyond knowing how to configure a specific CI/CD tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Reactive Ops to Proactive Reliability Engineering
&lt;/h3&gt;

&lt;p&gt;The old DevOps role was often reactive: something breaks, someone pages you, you fix it. Modern DevOps engineering is increasingly about building systems that are observable, resilient by design, and that catch problems before they reach production. SLOs, error budgets, chaos engineering, and progressive delivery have moved from advanced concepts to expected baseline knowledge.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rewriting the Job Description
&lt;/h2&gt;

&lt;p&gt;One of the biggest hiring mistakes companies make is copying and pasting a DevOps job description from three years ago. Here is how to think about each section differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Required Skills: Anchor to Principles, Not Tools
&lt;/h3&gt;

&lt;p&gt;Instead of: "Must have 3 years of experience with Jenkins"&lt;/p&gt;

&lt;p&gt;Write: "Experience building and maintaining CI/CD pipelines; familiarity with modern pipeline tools such as GitHub Actions, GitLab CI, or Tekton"&lt;/p&gt;

&lt;p&gt;The specific tool will change. The underlying competency, which includes understanding build graphs, artifact management, test integration, and deployment strategies, is what you actually need.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Fluency as an Explicit Requirement
&lt;/h3&gt;

&lt;p&gt;Be direct about this. If your team uses AI coding assistants, say so. Include language like:&lt;/p&gt;

&lt;p&gt;"Comfortable using AI-assisted development tools (GitHub Copilot, Cursor, etc.) for infrastructure code generation, with the judgment to critically review and validate AI-generated output before deployment."&lt;/p&gt;

&lt;p&gt;This attracts candidates who are already living in this workflow and signals to the market that your team is operating at the current frontier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Platform Engineering Mindset Section
&lt;/h3&gt;

&lt;p&gt;If your organization is moving toward an internal developer platform, make that explicit. Look for engineers who mention "developer experience" in their resume, who have built self-service tooling, or who have contributed to platform initiatives. This is a mindset distinction as much as a skills one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interview Design for the AI-Augmented DevOps Engineer
&lt;/h2&gt;

&lt;p&gt;The traditional DevOps interview often consists of trivia questions ("What is the difference between a Docker container and a VM?") and whiteboard exercises that test rote knowledge. This format is increasingly inadequate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Replace Trivia With Scenario-Based Problem Solving
&lt;/h3&gt;

&lt;p&gt;Present candidates with a real-world scenario. For example: "Our deployment pipeline is taking 45 minutes to complete. Walk me through how you would diagnose and improve this." You are not looking for a memorized answer. You want to see how they think, what questions they ask, and how they break down a system problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add an AI-Assisted Coding Round
&lt;/h3&gt;

&lt;p&gt;Give candidates access to an AI coding tool during a practical exercise. The task might be: "Use whatever tools you normally use to write a GitHub Actions workflow that builds a Docker image, runs security scanning, and pushes to a registry only on a tagged commit."&lt;/p&gt;

&lt;p&gt;Then, after they complete it, do a code review together. Ask them to explain every section. Ask them to identify what could go wrong. This evaluates both their ability to use AI tools effectively and their depth of understanding of the output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test for Security Instincts
&lt;/h3&gt;

&lt;p&gt;Security has become inseparable from DevOps. Ask candidates how they approach secrets management in pipelines. Ask them to review a YAML file with intentional security issues. The best DevOps engineers for this era have a security-first instinct, not just security awareness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluate Observability Thinking
&lt;/h3&gt;

&lt;p&gt;Ask candidates to describe how they would instrument a new service for production readiness. Do they think about the four golden signals? Do they mention structured logging, distributed tracing, and alerting on symptom rather than cause? Observability maturity is a strong signal of engineering depth.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "Good" Looks Like: A Profile of the Modern DevOps Engineer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The T-Shaped Generalist Who Can Go Deep
&lt;/h3&gt;

&lt;p&gt;The best DevOps hires are broad enough to understand the full software delivery lifecycle but deep enough in at least one or two areas to drive technical decisions. You want someone who understands Kubernetes networking at a conceptual level and can go deep on CI/CD pipeline design or infrastructure security when needed.&lt;/p&gt;

&lt;p&gt;Generalists who are shallow across the board tend to create dependency on vendor documentation and AI tools without sufficient judgment to catch problems. Specialists who cannot operate outside their lane struggle in the cross-functional nature of modern DevOps.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Builder Mindset With a Teacher's Heart
&lt;/h3&gt;

&lt;p&gt;DevOps engineers who build great internal tools but cannot explain them or enable other engineers to use them are underperforming their potential. In the era of platform engineering, the ability to create documentation, runbooks, onboarding guides, and self-service tooling that other engineers actually adopt is enormously valuable.&lt;/p&gt;

&lt;p&gt;Look for candidates who mention mentoring, documentation, or internal tooling adoption in their work history. These signals indicate someone who thinks about impact beyond their own output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comfort With Ambiguity and Rapid Change
&lt;/h3&gt;

&lt;p&gt;The tooling landscape in DevOps changes faster than almost any other discipline in software engineering. The candidate who thrives is the one who approaches a new tool with curiosity rather than resistance, who can get productive with an unfamiliar system quickly, and who updates their mental models when new information arrives.&lt;/p&gt;

&lt;p&gt;Ask candidates about a time they had to learn a new tool or technology quickly. Ask what their process is for staying current with the field. Their answer will tell you a lot about their growth orientation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to Find DevOps Engineers for This New Era
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Go Where Practitioners Actually Are
&lt;/h3&gt;

&lt;p&gt;LinkedIn is still useful for high-volume sourcing, but the most interesting DevOps engineers today are often active in communities that are harder to search. GitHub profiles with active open-source contributions, contributions to CNCF projects, activity in Slack communities like Kubernetes Slack or HashiCorp Discuss, and writing on platforms like dev.to are often better signals of genuine engagement than a polished resume.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluate GitHub as a Portfolio
&lt;/h3&gt;

&lt;p&gt;A candidate's GitHub profile, if they have public activity, can tell you more than a resume in some cases. Look for contributions to infrastructure tooling projects, well-documented repos with proper READMEs, issue and PR comments that show how they collaborate, and any personal projects that demonstrate initiative.&lt;/p&gt;

&lt;p&gt;Keep in mind that not every excellent engineer has an active public GitHub presence. This is a useful signal when present, not a disqualifier when absent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invest in Referral Networks
&lt;/h3&gt;

&lt;p&gt;DevOps engineering is a relatively small world, especially at the senior level. Engineers who are great at this work tend to know each other. A structured referral program that rewards your current DevOps team for quality introductions is often the highest-ROI sourcing channel for this discipline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider Non-Traditional Backgrounds
&lt;/h3&gt;

&lt;p&gt;Some of the most effective DevOps engineers in the AI-augmented era come from backgrounds that are not purely DevOps. Software engineers who developed a passion for infrastructure, sysadmins who went deep on automation, and data engineers who built MLOps pipelines all bring valuable perspective. Widening your definition of "DevOps background" can open up your candidate pool significantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Compensation and Retention in a Competitive Market
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benchmark Against Market Reality
&lt;/h3&gt;

&lt;p&gt;DevOps engineering compensation has increased substantially over the past several years, and the AI-augmented tier sits at the top of the range. Senior engineers with strong cloud architecture skills, platform engineering experience, and demonstrated AI fluency are in high demand across every industry vertical.&lt;/p&gt;

&lt;p&gt;Use current compensation data from sources like Levels.fyi, Glassdoor, and the Stack Overflow Developer Survey to benchmark your offers. Underpaying on initial offers increases your cost-per-hire through longer search cycles and increases attrition risk once you do hire.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make the Technical Environment Part of the Pitch
&lt;/h3&gt;

&lt;p&gt;Top DevOps engineers are often more motivated by the technical environment than the compensation package alone. During the interview process, be transparent about your infrastructure maturity, the technical debt situation, the tooling budget, and the level of autonomy engineers have to make architectural decisions.&lt;/p&gt;

&lt;p&gt;Engineers who are excited about working in an AI-augmented workflow want to know they will have access to the right tools and the freedom to build with them. If your team has standardized on modern tooling and has budget for AI coding assistants, make that visible in your employer brand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Clear Growth Paths
&lt;/h3&gt;

&lt;p&gt;One of the most common reasons DevOps engineers leave is a lack of visible career progression. Create and communicate clear ladders that distinguish between individual contributor depth (Staff DevOps Engineer, Principal Platform Engineer) and people leadership paths (Engineering Manager, Director of Platform Engineering). Engineers who see a future in your organization are significantly more likely to stay through the inevitable difficult stretches.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Hiring Mistakes to Avoid
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overweighting Certifications
&lt;/h3&gt;

&lt;p&gt;AWS, Google Cloud, and Kubernetes certifications are useful as a baseline signal that a candidate has studied these platforms. They are not a reliable indicator of ability to perform on the job. Some of the most effective DevOps engineers have no formal certifications. Some certified engineers struggle with ambiguous real-world problems.&lt;/p&gt;

&lt;p&gt;Use certifications as one data point among many, not as a filter or a strong positive signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Underweighting Soft Skills
&lt;/h3&gt;

&lt;p&gt;DevOps is inherently collaborative. Engineers in this role interface with software developers, security teams, product managers, and business stakeholders. The inability to communicate clearly, handle conflict constructively, or adapt communication style to the audience is a real performance risk, not just a culture-fit issue.&lt;/p&gt;

&lt;p&gt;Include behavioral interview questions that probe collaboration, conflict resolution, and cross-functional influence. Weight these answers seriously in your hiring decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiring for Today's Stack Instead of Tomorrow's Needs
&lt;/h3&gt;

&lt;p&gt;It is tempting to hire specifically for the tools you are using right now. But DevOps tooling evolves quickly, and a hire optimized purely for your current stack may struggle when you migrate to a new cloud provider, adopt a new orchestration platform, or integrate AI-powered operations tools.&lt;/p&gt;

&lt;p&gt;Prioritize adaptability and foundational understanding over tool-specific experience. The engineer who deeply understands container networking will figure out the next Kubernetes CNI plugin. The engineer who only knows how to configure one specific plugin may not.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building a DevOps Team That Thrives With AI
&lt;/h2&gt;

&lt;p&gt;The future of DevOps engineering is not about replacing human judgment with AI automation. It is about engineers who use AI as a force multiplier while maintaining the depth and discernment to ensure systems are secure, reliable, and maintainable.&lt;/p&gt;

&lt;p&gt;The teams that will thrive are those where DevOps engineers are curious about AI tools, rigorous in their review of AI-generated output, focused on developer experience as a product, and deeply grounded in the systems thinking that no LLM can fully replicate.&lt;/p&gt;

&lt;p&gt;When you hire with this profile in mind, you are not just filling a headcount. You are making a bet on how software delivery will actually work for the next five to ten years.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Hire for the Era You Are Actually In
&lt;/h2&gt;

&lt;p&gt;The gap between the DevOps role that most job descriptions describe and the role that modern engineering teams actually need has never been wider. YAML expertise, CI/CD configuration, and cloud platform knowledge remain important, but they are now table stakes, not differentiators.&lt;/p&gt;

&lt;p&gt;The engineers who will have the most impact in the coming years are those who combine that technical foundation with AI fluency, platform thinking, security instinct, and a genuine commitment to enabling the developers around them.&lt;/p&gt;

&lt;p&gt;Rethinking your hiring process, your job descriptions, your interview design, and your employer brand around these realities is not optional. It is the work of building an engineering organization that can actually deliver in the new era of software development.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Testing the Future: How to Hire Software Testers for Agentic UX and Generative UI</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Fri, 01 May 2026 12:19:54 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/testing-the-future-how-to-hire-software-testers-for-agentic-ux-and-generative-ui-3631</link>
      <guid>https://dev.to/emma_schmidt_/testing-the-future-how-to-hire-software-testers-for-agentic-ux-and-generative-ui-3631</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: The Testing Landscape Has Changed Forever
&lt;/h2&gt;

&lt;p&gt;The way software behaves has fundamentally shifted. Applications no longer follow&lt;br&gt;
predictable, scripted flows. They think, adapt, generate, and surprise. If you are&lt;br&gt;
still running QA the same way you did five years ago, you are already behind. To&lt;br&gt;
stay competitive in this new world, companies need to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-software-testers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;hire software testers&lt;/a&gt;&lt;/strong&gt; who&lt;br&gt;
understand not just how software works, but how intelligent software &lt;em&gt;decides&lt;/em&gt;. &lt;br&gt;
Agentic UX and Generative UI are two of the most disruptive trends reshaping&lt;br&gt;
product development today, and testing them requires an entirely new mindset,&lt;br&gt;
skill set, and toolbox.&lt;/p&gt;

&lt;p&gt;This blog explores what agentic UX and generative UI actually mean for QA teams,&lt;br&gt;
why traditional testing methods fall short, and how to build a team capable of&lt;br&gt;
ensuring quality in a world where the interface itself is no longer static.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Agentic UX and Why Does It Break Traditional Testing?
&lt;/h2&gt;

&lt;p&gt;Agentic UX refers to interfaces powered by &lt;strong&gt;&lt;a href="https://www.zignuts.com/cs/build-deploy-ai-agents-easily?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;AI agents&lt;/a&gt;&lt;/strong&gt;. These are systems that do&lt;br&gt;
not just respond to user input but actively take actions, make decisions, chain&lt;br&gt;
tasks together, and even call external tools and &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/mastering-api-architecture-ios?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;APIs&lt;/a&gt;&lt;/strong&gt; on behalf of the user.&lt;br&gt;
Think of an AI assistant that books your flight, adjusts your calendar, sends&lt;br&gt;
confirmation emails, and notifies your team, all triggered by a single prompt.&lt;/p&gt;

&lt;p&gt;The defining characteristic of an agentic system is its autonomy. It does not&lt;br&gt;
follow a fixed decision tree. It reasons, selects tools, and acts based on&lt;br&gt;
context. This creates a massive problem for traditional QA approaches because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Outputs are non-deterministic.&lt;/strong&gt; The same input can produce different outputs
depending on the model's state, context window, and retrieved information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flows are emergent.&lt;/strong&gt; There is no single, predictable path through the
application. The agent decides the path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failures are subtle.&lt;/strong&gt; The system might complete the task but do so in a way
that is slightly wrong, misleading, or harmful without throwing a single error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Side effects are real.&lt;/strong&gt; Agents take real-world actions. A bug in an agentic
system is not just a broken UI element. It could send an email, charge a card,
or delete a file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional test cases assume you know what the system will do next. Agentic UX&lt;br&gt;
removes that assumption entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Generative UI and How Does It Complicate Quality Assurance?
&lt;/h2&gt;

&lt;p&gt;Generative UI takes things one step further. Rather than generating text or data,&lt;br&gt;
these systems generate the actual user interface on the fly. A generative UI&lt;br&gt;
might render different components, layouts, buttons, and flows depending on who&lt;br&gt;
the user is, what they asked, and what the AI determined would be the best way&lt;br&gt;
to present information.&lt;/p&gt;

&lt;p&gt;This is not A/B testing. This is an AI making real-time design decisions at the&lt;br&gt;
component level. The implications for testing are enormous:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;There is no fixed interface to test.&lt;/strong&gt; If the UI renders differently each
time, traditional screenshot-based regression testing becomes nearly useless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility is unpredictable.&lt;/strong&gt; Can you guarantee WCAG compliance when a
screen reader has never seen this particular layout before?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand and design consistency may drift.&lt;/strong&gt; AI-generated interfaces can
introduce visual inconsistencies that no designer approved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User mental models are disrupted.&lt;/strong&gt; If the interface changes significantly
between sessions, users may not know where to find things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Testing generative UI requires evaluating not just functionality, but aesthetics,&lt;br&gt;
consistency, safety, and cognitive coherence. That is a tall order for a QA team&lt;br&gt;
trained only on Selenium scripts.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Skills Gap: What Traditional Testers Do Not Know Yet
&lt;/h2&gt;

&lt;p&gt;Most software testers today are excellent at what they were trained to do. They&lt;br&gt;
can write test plans, identify edge cases, run regression suites, and file&lt;br&gt;
detailed bug reports. These skills remain valuable. However, agentic and&lt;br&gt;
generative systems require additional competencies that most QA professionals&lt;br&gt;
have not yet developed.&lt;/p&gt;

&lt;p&gt;Here is where the gap typically lies:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Probabilistic Thinking
&lt;/h3&gt;

&lt;p&gt;Traditional testers operate in a binary world: pass or fail. Agentic systems&lt;br&gt;
operate in a probabilistic world: mostly correct, sometimes wrong, occasionally&lt;br&gt;
harmful. A tester working with AI-powered software needs to understand&lt;br&gt;
confidence scores, output distributions, and acceptable variance ranges.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Prompt Engineering Literacy
&lt;/h3&gt;

&lt;p&gt;If you are testing an agentic system, you need to know how prompts influence&lt;br&gt;
behavior. This does not mean testers need to be machine learning engineers. But&lt;br&gt;
they need to understand how changing a system prompt, adjusting context, or&lt;br&gt;
modifying user input can shift the agent's behavior. Prompt-based test design&lt;br&gt;
is a real discipline that is quickly becoming essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Evaluation Frameworks for LLM Output
&lt;/h3&gt;

&lt;p&gt;When the output is text, code, or a UI layout generated by a language model, how&lt;br&gt;
do you decide if it is correct? Traditional assertions break down here. Testers&lt;br&gt;
need exposure to evaluation frameworks such as G-Eval, RAGAS, or custom rubric&lt;br&gt;
scoring approaches that assess quality along multiple dimensions: accuracy,&lt;br&gt;
helpfulness, safety, tone, and coherence.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Observability and Tracing
&lt;/h3&gt;

&lt;p&gt;Agentic systems are multi-step pipelines. When something goes wrong, the failure&lt;br&gt;
may have occurred three tool calls ago. Testers need to work with tracing tools&lt;br&gt;
like LangSmith, Arize, or custom logging dashboards that surface the internal&lt;br&gt;
state of agent reasoning. Understanding how to read a trace is quickly becoming a&lt;br&gt;
core QA skill.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Human-in-the-Loop Evaluation
&lt;/h3&gt;

&lt;p&gt;Some outputs simply cannot be validated programmatically. Testers working with&lt;br&gt;
generative AI need to design human evaluation workflows, write rubrics, train&lt;br&gt;
raters, and synthesize qualitative feedback alongside automated metrics.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Hire Software Testers for Agentic and Generative Systems
&lt;/h2&gt;

&lt;p&gt;Knowing the skills gap is half the battle. The other half is knowing how to&lt;br&gt;
identify candidates who have closed that gap or who have the foundation to close&lt;br&gt;
it quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Define the Role Accurately
&lt;/h3&gt;

&lt;p&gt;Before posting a job description, be honest about what you are building. Too many&lt;br&gt;
companies post a standard "QA Engineer" role when they are actually building&lt;br&gt;
AI-powered, non-deterministic software. Your job description should explicitly&lt;br&gt;
mention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experience with AI/ML systems testing or familiarity with LLM-based applications&lt;/li&gt;
&lt;li&gt;Comfort with non-deterministic outputs&lt;/li&gt;
&lt;li&gt;Exposure to evaluation frameworks or model monitoring tools&lt;/li&gt;
&lt;li&gt;Understanding of agent pipelines or multi-step AI workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This specificity will filter out candidates who are not ready and attract those&lt;br&gt;
who are exploring this frontier intentionally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Look for Exploratory Testing Instincts
&lt;/h3&gt;

&lt;p&gt;Agentic systems cannot be fully tested with scripted test cases. You need testers&lt;br&gt;
who are naturally curious, who enjoy breaking things by thinking laterally, and&lt;br&gt;
who instinctively ask "what happens if I do this in an unexpected way?" Structured&lt;br&gt;
exploratory testing skills are more valuable here than the ability to maintain a&lt;br&gt;
large Selenium suite.&lt;/p&gt;

&lt;p&gt;During interviews, present candidates with an agentic demo and ask them to&lt;br&gt;
explore it for fifteen minutes. Watch how they think. Do they try edge cases? Do&lt;br&gt;
they probe for bias? Do they think about downstream consequences of the agent's&lt;br&gt;
actions? That behavior tells you more than any resume line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assess Analytical Writing and Bug Articulation
&lt;/h3&gt;

&lt;p&gt;AI bugs are hard to describe. The output was not wrong exactly, but it was&lt;br&gt;
misleading. The agent completed the task, but its reasoning was flawed. The UI&lt;br&gt;
rendered correctly on the first load but generated inconsistently afterward. &lt;br&gt;
Testers who can articulate these nuanced failures clearly, in writing, are&lt;br&gt;
invaluable. Ask candidates to write a bug report for a described AI failure&lt;br&gt;
scenario and evaluate the clarity and depth of their analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prioritize Intellectual Curiosity Over Tool Familiarity
&lt;/h3&gt;

&lt;p&gt;The tooling landscape for AI testing is changing every few months. Candidates who&lt;br&gt;
are attached to specific tools will struggle to adapt. Look for testers who&lt;br&gt;
demonstrate a pattern of learning new things, experimenting with emerging tools,&lt;br&gt;
and building their own evaluation approaches when off-the-shelf solutions do not&lt;br&gt;
fit. Curiosity is the most durable skill in this domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consider Cross-Functional Backgrounds
&lt;/h3&gt;

&lt;p&gt;Some of the best AI-era testers come from non-traditional backgrounds. UX&lt;br&gt;
researchers who understand how users interpret generative interfaces. Data&lt;br&gt;
analysts who can evaluate output quality at scale. Technical writers who have&lt;br&gt;
worked closely with LLM outputs and know what "good" looks like qualitatively.&lt;br&gt;
Do not limit your search to traditional QA pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the Team Around Agentic Testing
&lt;/h2&gt;

&lt;p&gt;Hiring individual testers is only part of the solution. You also need to think&lt;br&gt;
about how the team is structured and what supporting infrastructure they have&lt;br&gt;
access to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a QA-AI Collaboration Layer
&lt;/h3&gt;

&lt;p&gt;Your testers should have regular access to AI engineers, prompt designers, and&lt;br&gt;
data scientists. In agentic systems, the boundary between infrastructure and UX&lt;br&gt;
is blurry. A test that appears to be a UX &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/vibe-coding-failures-project-rescue?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;failure&lt;/a&gt;&lt;/strong&gt; might actually be a retrieval&lt;br&gt;
failure, a prompt regression, or a model degradation issue. Teams that silo QA&lt;br&gt;
from AI engineering will consistently misdiagnose failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invest in Evaluation Infrastructure
&lt;/h3&gt;

&lt;p&gt;Good agentic testing requires good tooling. This means building or adopting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LLM evaluation pipelines&lt;/strong&gt; that score outputs against defined rubrics
automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace logging&lt;/strong&gt; that captures every step of an agent's reasoning chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regression benchmarks&lt;/strong&gt; that detect when a model update has shifted behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synthetic user simulators&lt;/strong&gt; that can generate diverse, adversarial, and
edge-case inputs at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this infrastructure, your testers are flying blind no matter how skilled&lt;br&gt;
they are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop Internal Red-Teaming Practices
&lt;/h3&gt;

&lt;p&gt;Red-teaming in AI testing means deliberately trying to make the system behave&lt;br&gt;
badly. This includes probing for hallucinations, testing for harmful outputs,&lt;br&gt;
attempting prompt injection attacks, checking for biased responses, and exploring&lt;br&gt;
failure modes that a standard user would never encounter but a malicious one might.&lt;/p&gt;

&lt;p&gt;Build a red-teaming rotation into your QA process. Every major release should&lt;br&gt;
include a structured red-team session where testers actively try to break the&lt;br&gt;
system's guardrails and logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Evaluation Metrics That Actually Matter for Agentic UX
&lt;/h2&gt;

&lt;p&gt;Knowing what to measure is as important as knowing how to measure it. Here are&lt;br&gt;
the metrics that teams testing agentic and generative systems should track:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task Completion Rate&lt;/strong&gt; measures how often the agent successfully accomplishes&lt;br&gt;
what the user intended, not just what the user literally said.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faithfulness&lt;/strong&gt; tracks whether the agent's reasoning and outputs are grounded in&lt;br&gt;
actual retrieved data rather than fabricated information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency Under Load&lt;/strong&gt; evaluates whether the system remains usable when multiple&lt;br&gt;
agents are operating simultaneously or handling complex, multi-step requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hallucination Rate&lt;/strong&gt; quantifies how often the system produces confident but&lt;br&gt;
incorrect information. This should be tracked across different input categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency Score&lt;/strong&gt; for generative UI measures how visually and structurally&lt;br&gt;
consistent the interface remains across repeated similar interactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side Effect Accuracy&lt;/strong&gt; tracks whether the real-world actions an agent takes&lt;br&gt;
(emails sent, records updated, APIs called) are exactly what the user intended&lt;br&gt;
and nothing more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recovery Behavior&lt;/strong&gt; assesses how the system behaves when it encounters an&lt;br&gt;
ambiguous request, a tool failure, or an out-of-scope query. Does it fail&lt;br&gt;
gracefully or silently?&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes Companies Make When Hiring for AI Testing Roles
&lt;/h2&gt;

&lt;p&gt;Even companies that recognize the need for specialized testers often make&lt;br&gt;
predictable mistakes in how they build their QA strategy for agentic systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake 1: Treating AI testing as purely automated.&lt;/strong&gt; Automated evaluation is&lt;br&gt;
essential, but it cannot replace human judgment for nuanced, contextual failures.&lt;br&gt;
Companies that automate everything miss the subtle quality issues that matter most&lt;br&gt;
to real users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake 2: Underestimating the safety dimension.&lt;/strong&gt; Testing an agentic system&lt;br&gt;
that takes real-world actions is not just a quality problem. It is a safety and&lt;br&gt;
liability problem. Companies should treat safety testing as a first-class concern,&lt;br&gt;
not an afterthought.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake 3: Hiring only for technical skills.&lt;/strong&gt; Evaluating whether a generative&lt;br&gt;
UI is usable, trustworthy, and cognitively coherent requires empathy, design&lt;br&gt;
thinking, and user psychology knowledge. Pure technical testers will miss this&lt;br&gt;
dimension entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake 4: Skipping regression baselines.&lt;/strong&gt; When you update a model or change&lt;br&gt;
a system prompt, you need to know whether behavior changed and in what direction.&lt;br&gt;
Teams that lack behavioral baselines cannot answer this question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake 5: Treating testing as a gate rather than a continuous process.&lt;/strong&gt;&lt;br&gt;
Agentic systems evolve continuously through model updates, retrieval index&lt;br&gt;
changes, and prompt adjustments. Testing cannot be a phase that ends at launch.&lt;br&gt;
It needs to be a continuous monitoring and evaluation function embedded into the&lt;br&gt;
production pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Future of QA: Testers as AI Collaborators
&lt;/h2&gt;

&lt;p&gt;There is a broader philosophical shift happening in quality assurance right now.&lt;br&gt;
For decades, testers verified that software did what humans designed it to do.&lt;br&gt;
In the agentic era, testers are verifying that software does what humans&lt;br&gt;
&lt;em&gt;intended&lt;/em&gt;, which is a much harder problem when the software reasons and decides&lt;br&gt;
for itself.&lt;/p&gt;

&lt;p&gt;The best testers working in this space are not just finding bugs. They are&lt;br&gt;
shaping the behavioral contract between AI systems and users. They are defining&lt;br&gt;
what "good enough" looks like for non-deterministic outputs. They are advocating&lt;br&gt;
for users whose cognitive models cannot keep up with interfaces that change and&lt;br&gt;
adapt in real time.&lt;/p&gt;

&lt;p&gt;This is meaningful, complex, intellectually demanding work. It sits at the&lt;br&gt;
intersection of cognitive science, software engineering, AI ethics, and&lt;br&gt;
interaction design. The professionals who can operate at that intersection&lt;br&gt;
are genuinely rare and genuinely valuable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Build for the Interface That Learns
&lt;/h2&gt;

&lt;p&gt;The shift to agentic UX and generative UI is not a future trend. It is&lt;br&gt;
happening right now across product categories from customer service to developer&lt;br&gt;
tooling to healthcare to finance. Companies that delay building a testing&lt;br&gt;
capability suited to these systems are accumulating invisible technical and&lt;br&gt;
reputational debt.&lt;/p&gt;

&lt;p&gt;Hiring the right testers for this era means looking beyond traditional QA&lt;br&gt;
credentials. It means finding people who think probabilistically, who are&lt;br&gt;
comfortable with ambiguity, who can evaluate quality without a binary answer&lt;br&gt;
key, and who are excited rather than intimidated by systems that surprise them.&lt;/p&gt;

&lt;p&gt;It means investing in the infrastructure, culture, and collaboration models that&lt;br&gt;
let those testers do their best work. And it means treating quality assurance not&lt;br&gt;
as a bottleneck before launch, but as a continuous, living function that evolves&lt;br&gt;
alongside the AI systems it is responsible for.&lt;/p&gt;

&lt;p&gt;The interface of the future is one that thinks, generates, and adapts. Your&lt;br&gt;
testing practice needs to be ready to meet it.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>How to Hire QA Automation Testers Who Master Self-Healing Frameworks</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Fri, 01 May 2026 11:30:54 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/how-to-hire-qa-automation-testers-who-master-self-healing-frameworks-50k1</link>
      <guid>https://dev.to/emma_schmidt_/how-to-hire-qa-automation-testers-who-master-self-healing-frameworks-50k1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: The New Standard in QA Hiring
&lt;/h2&gt;

&lt;p&gt;The world of software quality assurance has changed dramatically over the last few years. Traditional manual testing no longer cuts it for fast-moving engineering teams, and basic automation scripts break the moment a developer renames a button or shifts a layout element. This is precisely why so many companies today are racing to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-qa-automation-testers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Hire QA Automation Testers&lt;/a&gt;&lt;/strong&gt; who not only understand modern test automation but have hands-on experience with self-healing &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/top-5-javascript-frameworks-for-2023?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;frameworks&lt;/a&gt;&lt;/strong&gt; that keep test suites stable, reliable, and low-maintenance. If your organization is struggling with brittle tests, high maintenance costs, and delayed releases, you are not alone and the solution starts with knowing exactly who to look for and how to evaluate them.&lt;/p&gt;

&lt;p&gt;This guide will walk you through everything: what self-healing frameworks actually are, why they matter, what skills to screen for, how to structure your interview process, and where to find the best candidates in today's competitive talent market.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Self-Healing Frameworks and Why Do They Matter?
&lt;/h2&gt;

&lt;p&gt;Before you can hire the right person, your team needs to understand what self-healing test automation actually means.&lt;/p&gt;

&lt;p&gt;A self-healing framework is an AI-assisted or rules-based system that automatically detects when a test element locator has broken and repairs it without human intervention. In traditional test automation, if a developer changes the &lt;code&gt;id&lt;/code&gt; attribute of a button from &lt;code&gt;submit-btn&lt;/code&gt; to &lt;code&gt;cta-button&lt;/code&gt;, every test that referenced the old locator will fail. A tester then has to manually find the broken locator and fix it. Multiply this across hundreds of tests and dozens of sprints, and you have a maintenance nightmare.&lt;/p&gt;

&lt;p&gt;Self-healing frameworks solve this by using techniques such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple locator strategies&lt;/strong&gt;: The framework stores backup locators (XPath, CSS selector, text, position) and tries each one when the primary fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered element matching&lt;/strong&gt;: Tools like Healenium, Testim, mabl, and Applitools use machine learning to identify the correct element based on visual and structural similarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic locator updates&lt;/strong&gt;: After finding the correct element using a fallback, the framework can automatically update the locator in the codebase, so the fix is permanent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual regression detection&lt;/strong&gt;: Some frameworks can identify UI changes by comparing screenshots pixel-by-pixel or using AI-based visual comparison.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business value is enormous. Teams that implement self-healing frameworks report up to 80% reduction in test maintenance time, faster release cycles, and far fewer false-positive failures that slow down CI/CD pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Skills to Look for When You Hire QA Automation Testers
&lt;/h2&gt;

&lt;p&gt;Not every automation tester has experience with self-healing tools, and that is fine as long as they have the right foundation. Here is a breakdown of the skill tiers you should evaluate.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Strong Foundation in Test Automation Principles
&lt;/h3&gt;

&lt;p&gt;A candidate cannot leverage self-healing frameworks without first understanding automation fundamentals. Screen for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proficiency in at least one major automation framework: Selenium WebDriver, Playwright, &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/cypress-e2e-testing-guide-qa?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;&lt;/strong&gt;, or Appium for mobile&lt;/li&gt;
&lt;li&gt;Solid understanding of the Page Object Model (POM) and other design patterns&lt;/li&gt;
&lt;li&gt;Experience writing maintainable, reusable test scripts&lt;/li&gt;
&lt;li&gt;Knowledge of synchronization strategies: explicit waits, implicit waits, and polling&lt;/li&gt;
&lt;li&gt;Comfort with version control, specifically Git branching and pull request workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Candidates who cannot explain why the Page Object Model exists or who have never worked in a CI/CD pipeline should be a concern, regardless of how many tools they list on their resume.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hands-On Experience with Self-Healing Tools
&lt;/h3&gt;

&lt;p&gt;This is the differentiating factor. Look for direct experience with one or more of the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Healenium&lt;/strong&gt;: An open-source self-healing extension for Selenium that stores element locators in a database and automatically finds new locators when old ones fail. Candidates familiar with Healenium should understand how it integrates with existing Selenium WebDriver code and how it reports healed selectors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testim&lt;/strong&gt;: A low-code/full-code AI-powered testing platform that uses machine learning to stabilize element identification. Look for candidates who have worked with Testim's smart locators and understand when to override AI decisions with manual controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mabl&lt;/strong&gt;: A cloud-based intelligent testing platform with built-in self-healing that continuously learns from application changes. Experience here often signals familiarity with exploratory automation and visual testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applitools Eyes&lt;/strong&gt;: Focused on visual AI testing, Applitools is ideal for teams that need to catch visual regressions in addition to functional test failures. Strong candidates can explain how visual testing complements traditional locator-based tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LambdaTest SmartUI&lt;/strong&gt;: A visual regression and smart automation testing platform. Candidates with this experience are usually comfortable running tests across multiple browsers and environments in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. AI and Machine Learning Literacy
&lt;/h3&gt;

&lt;p&gt;You do not need your QA tester to build machine learning models, but they should understand the concepts that power the tools they use. A quality candidate should be able to explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How similarity scoring works when a self-healing tool selects a replacement locator&lt;/li&gt;
&lt;li&gt;The difference between deterministic and probabilistic element matching&lt;/li&gt;
&lt;li&gt;When to trust the AI and when to intervene manually&lt;/li&gt;
&lt;li&gt;How training data and historical test runs influence tool behavior over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This literacy separates testers who use self-healing tools as a black box from those who can debug issues when the AI makes the wrong call.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. CI/CD and DevOps Integration Skills
&lt;/h3&gt;

&lt;p&gt;Self-healing frameworks are most valuable when embedded in an automated pipeline. Your ideal candidate should have experience with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrating test suites into Jenkins, GitHub Actions, GitLab CI, or CircleCI&lt;/li&gt;
&lt;li&gt;Configuring test parallelization across browsers and environments&lt;/li&gt;
&lt;li&gt;Setting up test result reporting dashboards using Allure, ReportPortal, or similar tools&lt;/li&gt;
&lt;li&gt;Triggering self-healing reports as part of post-build steps&lt;/li&gt;
&lt;li&gt;Understanding Docker and containerized test execution environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Programming and Scripting Proficiency
&lt;/h3&gt;

&lt;p&gt;Even low-code tools require scripting knowledge when customization is needed. The specific language matters less than the ability to write clean, maintainable code. Prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java or Python for Selenium-based frameworks&lt;/li&gt;
&lt;li&gt;JavaScript or TypeScript for Playwright and Cypress&lt;/li&gt;
&lt;li&gt;Ability to write utility functions, custom waits, and reusable helper classes&lt;/li&gt;
&lt;li&gt;Familiarity with data-driven and keyword-driven testing approaches&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Structure Your Interview Process
&lt;/h2&gt;

&lt;p&gt;A strong hiring process for QA automation specialists should be layered and practical. Here is a three-stage structure that works well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 1: Technical Phone Screen (30 to 45 Minutes)
&lt;/h3&gt;

&lt;p&gt;The goal here is to filter out candidates who have inflated their resumes. Ask open-ended questions that require real understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Walk me through how Healenium heals a broken locator. What happens step by step?"&lt;/li&gt;
&lt;li&gt;"You have 500 automated tests and 20% of them are failing due to locator changes after a UI redesign. How do you approach fixing this efficiently?"&lt;/li&gt;
&lt;li&gt;"What is the difference between a flaky test and a broken test? How do you handle each?"&lt;/li&gt;
&lt;li&gt;"Have you ever had a self-healing tool make an incorrect decision and apply the wrong locator? How did you catch it and resolve it?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions reveal whether a candidate has genuine hands-on experience or is simply familiar with the names of tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Technical Assessment (Take-Home or Live Coding, 2 to 3 Hours)
&lt;/h3&gt;

&lt;p&gt;Give candidates a real-world scenario. A strong take-home assessment could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A broken Selenium test suite where locators have intentionally been changed&lt;/li&gt;
&lt;li&gt;A task to integrate Healenium or another self-healing mechanism&lt;/li&gt;
&lt;li&gt;Writing a test for a sample application that includes a dynamic UI component&lt;/li&gt;
&lt;li&gt;A short written explanation of their approach and any tradeoffs they considered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Evaluate not just whether the tests pass but how the candidate structured their code, handled edge cases, and communicated their thinking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: System Design and Culture Interview (60 Minutes)
&lt;/h3&gt;

&lt;p&gt;The final stage should assess strategic thinking and team fit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"How would you design a self-healing test architecture for a team of 15 engineers shipping 10 times per week?"&lt;/li&gt;
&lt;li&gt;"What metrics would you track to measure the success of your self-healing implementation?"&lt;/li&gt;
&lt;li&gt;"How do you balance test coverage with maintenance costs?"&lt;/li&gt;
&lt;li&gt;"Describe a time you had to advocate for a testing improvement that was initially met with resistance."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stage reveals whether the candidate can think beyond individual scripts and contribute to team-level quality strategy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Red Flags to Watch Out For
&lt;/h2&gt;

&lt;p&gt;Hiring the wrong QA automation tester is expensive. Watch out for these warning signs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over-reliance on record-and-playback tools&lt;/strong&gt;: Candidates who mention that they primarily use record-and-playback without coding often struggle when tests need real customization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inability to explain tool internals&lt;/strong&gt;: If someone says they use Testim but cannot explain what smart locators are or how the AI learns from test runs, they likely have surface-level experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No experience with CI/CD&lt;/strong&gt;: Modern QA automation is inseparable from pipelines. A candidate with zero CI/CD experience will require significant ramp-up time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating test failures as always being "flaky"&lt;/strong&gt;: Some testers dismiss failures as flakiness without investigating root causes. This attitude leads to ignored bugs and unreliable test suites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No understanding of test reporting and analytics&lt;/strong&gt;: A self-healing framework generates valuable data about what is being healed and why. Candidates should know how to interpret this data to improve the application and the tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to Find Top QA Automation Talent
&lt;/h2&gt;

&lt;p&gt;Finding candidates who specialize in self-healing frameworks requires more targeted sourcing than posting a generic job description on a job board.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specialized Job Boards and Communities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TestingConferences.com and Ministry of Testing&lt;/strong&gt;: Active communities where senior QA professionals discuss tools, frameworks, and best practices. Posting here signals that you understand the QA profession.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: Use advanced filters to search for candidates with specific tool keywords like "Healenium," "Testim," or "Applitools."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: Search for contributors to open-source QA projects, particularly those who have contributed to or forked self-healing tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conferences and Meetups
&lt;/h3&gt;

&lt;p&gt;Attend or sponsor events like SeleniumConf, Appium Conf, or local QA meetups. Professionals who attend these events are usually deeply invested in their craft and aware of emerging technologies like self-healing frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Staffing Agencies Specializing in QA
&lt;/h3&gt;

&lt;p&gt;General-purpose tech staffing firms often lack the domain knowledge to screen QA automation candidates effectively. Look for agencies that specialize in software testing talent, as they are better equipped to evaluate technical skills before presenting candidates to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Upskilling
&lt;/h3&gt;

&lt;p&gt;Do not overlook your existing team. If you have strong automation testers who lack self-healing experience, a targeted training investment in tools like Healenium or Testim can be faster and more cost-effective than an external hire. This approach also improves retention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing a Job Description That Attracts the Right Candidates
&lt;/h2&gt;

&lt;p&gt;Vague job descriptions attract vague candidates. Be specific about what you are looking for. Here is a structure that works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Title&lt;/strong&gt;: QA Automation Engineer with AI-Powered Testing Experience&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Will Do&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design, build, and maintain automated test suites using Playwright and Healenium&lt;/li&gt;
&lt;li&gt;Integrate self-healing test mechanisms into our CI/CD pipeline (GitHub Actions)&lt;/li&gt;
&lt;li&gt;Monitor and analyze test healing reports to identify patterns and improve application stability&lt;/li&gt;
&lt;li&gt;Collaborate with developers to shift quality left and embed testing in the development process&lt;/li&gt;
&lt;li&gt;Define and track quality metrics including flakiness rates, healing frequency, and test coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What We Are Looking For&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 or more years of hands-on experience in QA automation&lt;/li&gt;
&lt;li&gt;Direct experience with at least one self-healing framework (Healenium, Testim, mabl, or Applitools)&lt;/li&gt;
&lt;li&gt;Proficiency in JavaScript/&lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/typescript-first-nodejs-backend-architecture-2026?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=5" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt; or Python&lt;/li&gt;
&lt;li&gt;Experience integrating tests into CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Excellent communication skills and the ability to explain test strategy to non-technical stakeholders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nice to Have&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experience with visual regression testing&lt;/li&gt;
&lt;li&gt;Contributions to open-source testing projects&lt;/li&gt;
&lt;li&gt;Familiarity with Docker and containerized test environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being specific about tools and responsibilities will filter in serious candidates and filter out those who simply include buzzwords in their resume.&lt;/p&gt;




&lt;h2&gt;
  
  
  Compensation and Market Expectations
&lt;/h2&gt;

&lt;p&gt;Self-healing framework expertise is a premium skill set. Budgeting appropriately is critical to attracting the right talent.&lt;/p&gt;

&lt;p&gt;As of 2025, QA automation engineers with AI testing experience typically command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Junior level (1 to 3 years)&lt;/strong&gt;: $70,000 to $95,000 per year in the US, depending on location and company size&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mid level (3 to 6 years)&lt;/strong&gt;: $95,000 to $130,000 per year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Senior level (6 or more years, architecture experience)&lt;/strong&gt;: $130,000 to $170,000 or more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For contract or freelance engagements, expect hourly rates between $60 and $120 depending on specialization and platform.&lt;/p&gt;

&lt;p&gt;If your budget is below market rate, consider offering strong non-monetary benefits: remote flexibility, access to cutting-edge tools, conference budgets, and clear career advancement paths. Senior QA professionals place high value on environments where their expertise is respected and invested in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building a Culture That Retains QA Automation Experts
&lt;/h2&gt;

&lt;p&gt;Hiring is only half the battle. Retention requires building an environment where QA professionals are treated as first-class engineering citizens, not an afterthought.&lt;/p&gt;

&lt;p&gt;Key practices that improve QA retention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Involve QA from day one&lt;/strong&gt;: Include testers in sprint planning, design reviews, and architecture discussions. This shift-left approach produces better software and makes testers feel valued.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide access to the latest tools&lt;/strong&gt;: QA professionals who are passionate about their craft want to work with the best tools available. Budget for premium licenses where appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encourage knowledge sharing&lt;/strong&gt;: Create space for testers to share what they are learning, whether through internal tech talks, blog posts, or documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define clear career paths&lt;/strong&gt;: Many QA engineers leave because they see no path to advancement. Create explicit senior, staff, and principal-level tracks within your QA organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Celebrate quality wins&lt;/strong&gt;: When a self-healing framework catches a regression before it reaches production, make that visible. Recognition reinforces the value of the work being done.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The decision to hire QA automation engineers who specialize in self-healing frameworks is a strategic investment, not just a staffing decision. As applications grow in complexity and release cycles continue to compress, the cost of brittle, manually-maintained test suites becomes unbearable. Teams that adopt self-healing automation gain a competitive edge through faster feedback loops, higher test reliability, and significantly lower maintenance overhead.&lt;/p&gt;

&lt;p&gt;The key to success lies in knowing what to look for: a strong automation foundation, genuine hands-on experience with self-healing tools, AI literacy, and the ability to integrate testing into modern DevOps pipelines. Pair that with a thoughtful interview process, a competitive compensation package, and a culture that respects QA as a core engineering discipline, and you will be well-positioned to build a world-class quality engineering team.&lt;/p&gt;

&lt;p&gt;Start with clarity about your needs, be specific in how you evaluate candidates, and invest in the long-term growth of the people you bring on board. The results will show up directly in your product quality, your release velocity, and your customer satisfaction scores.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Quality is not an act, it is a habit, and the right QA automation engineer will help your entire team build that habit at scale.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Optimizing Performance: Why You Should Hire Flutter Developers for High-FPS Mobile Apps</title>
      <dc:creator>Emma Schmidt</dc:creator>
      <pubDate>Tue, 28 Apr 2026 06:41:24 +0000</pubDate>
      <link>https://dev.to/emma_schmidt_/optimizing-performance-why-you-should-hire-flutter-developers-for-high-fps-mobile-apps-54h2</link>
      <guid>https://dev.to/emma_schmidt_/optimizing-performance-why-you-should-hire-flutter-developers-for-high-fps-mobile-apps-54h2</guid>
      <description>&lt;p&gt;In a world where users abandon apps after a single laggy scroll or a frozen animation, performance is no longer a luxury. It is a survival requirement. Businesses across every vertical, from fintech to fitness, from &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/boost-ecommerce-sales-ai-recommendation-engines?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=4" rel="noopener noreferrer"&gt;e-commerce&lt;/a&gt;&lt;/strong&gt; to edtech, are doubling down on mobile performance because they know that frame drops kill conversions. If you want an application that runs at a consistent 60 FPS or even 120 FPS on modern devices, the framework you choose and the team behind it will define your success. This is precisely why hundreds of companies worldwide choose to &lt;strong&gt;&lt;a href="https://www.zignuts.com/hire-flutter-developers?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=4" rel="noopener noreferrer"&gt;hire Flutter developers&lt;/a&gt;&lt;/strong&gt; to build their mobile products. Flutter's architecture, rendering engine, and developer ecosystem are uniquely engineered for high-performance mobile apps, and in this blog, we will break down exactly why that is the case.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does "High FPS" Actually Mean for Mobile Apps?
&lt;/h2&gt;

&lt;p&gt;Before diving into Flutter specifics, it helps to understand what frame rate means in the context of mobile UX.&lt;/p&gt;

&lt;p&gt;FPS stands for frames per second. Every animation, scroll, transition, and tap feedback on your screen is rendered as a series of still frames. When those frames are delivered fast enough, the human eye perceives fluid motion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;60 FPS&lt;/strong&gt; is the industry baseline. At this rate, each frame has a budget of approximately 16 milliseconds to be prepared and rendered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;90 FPS and 120 FPS&lt;/strong&gt; are becoming the new standards on flagship Android devices and iPhones with ProMotion displays.&lt;/li&gt;
&lt;li&gt;Dropping below 60 FPS even briefly creates what users call "jank," the stuttery, laggy feeling that immediately signals a low-quality app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High FPS is not just about visual aesthetics. Research consistently shows that smoother apps lead to longer sessions, better retention, and higher revenue. Every dropped frame is a micro-frustration, and those micro-frustrations add up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Most Cross-Platform Frameworks Struggle with FPS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/boost-react-native-performance?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=4" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;&lt;/strong&gt;, Ionic, Xamarin, and other cross-platform frameworks have served developers well for years, but they share a fundamental architectural challenge: the JavaScript bridge or the reliance on native UI components introduces latency in the rendering pipeline.&lt;/p&gt;

&lt;p&gt;In React Native, for instance, your JavaScript logic communicates with the native thread through a bridge. Every time the UI needs to update, data crosses this bridge, which introduces delay. Heavy animations or complex screens can push this bridge to its limits, causing frame drops that are hard to fix without writing native code.&lt;/p&gt;

&lt;p&gt;Ionic and Cordova-based frameworks wrap a web view, which means they are essentially running a browser inside your app. Web views are powerful, but they are not optimized for 60+ FPS native experiences, especially on mid-range Android devices.&lt;/p&gt;

&lt;p&gt;This architectural bottleneck is precisely the gap Flutter was built to close.&lt;/p&gt;




&lt;h2&gt;
  
  
  Flutter's Rendering Architecture: The Core Reason for High Performance
&lt;/h2&gt;

&lt;p&gt;Flutter takes a radically different approach. Instead of relying on native UI widgets provided by Android or iOS, Flutter brings its own rendering engine called &lt;strong&gt;Impeller&lt;/strong&gt; (previously Skia). This means Flutter draws every pixel on the screen itself, directly on the GPU canvas, bypassing the OS widget system entirely.&lt;/p&gt;

&lt;p&gt;Here is why that matters for performance:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. No Bridge, No Bottleneck
&lt;/h3&gt;

&lt;p&gt;Flutter uses Dart as its programming language. Dart compiles to native ARM machine code ahead of time (AOT compilation). There is no JavaScript bridge, no virtual machine overhead at runtime. Your Dart logic runs as fast as native code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Widget Tree and the Render Tree Are in the Same Process
&lt;/h3&gt;

&lt;p&gt;In Flutter, the UI description (Widget tree), the layout computation (Element tree), and the actual painting (RenderObject tree) all live in the same Dart isolate. Updates propagate through these layers without any inter-process communication. This keeps the rendering loop tight and predictable.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Impeller: Built for the Modern GPU
&lt;/h3&gt;

&lt;p&gt;Flutter's newer rendering backend, Impeller, was purpose-built to eliminate shader compilation jank, which was one of the last remaining performance complaints about Flutter on iOS. Impeller pre-compiles shaders at build time rather than lazily compiling them at runtime. The result is consistent frame times with no first-frame jitter.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Compositor Layers and Repaint Boundaries
&lt;/h3&gt;

&lt;p&gt;Flutter's compositor intelligently manages layers. Developers can use &lt;code&gt;RepaintBoundary&lt;/code&gt; widgets to isolate parts of the widget tree, ensuring that an animation in one corner of the screen does not force a repaint of the entire UI. Experienced Flutter developers know how to use these tools to squeeze every millisecond of frame budget.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dart's Role in Performance: AOT Compilation and Isolates
&lt;/h2&gt;

&lt;p&gt;Dart is not just a language choice. It is a deliberate performance decision. Here is how Dart contributes to high-FPS Flutter apps:&lt;/p&gt;

&lt;h3&gt;
  
  
  AOT Compilation in Production
&lt;/h3&gt;

&lt;p&gt;When you build a Flutter app for release, Dart compiles to native ARM or x86 machine code. There is no interpreter, no JIT warmup penalty in production. The app starts fast and stays fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  JIT Compilation in Development
&lt;/h3&gt;

&lt;p&gt;During development, Dart uses JIT compilation, which is what powers Flutter's legendary hot reload. You change a line of code, hit save, and see the result in under a second without losing app state. This dramatically shortens the feedback loop for developers, meaning more iterations and better-optimized UI in the same time frame.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dart Isolates for Background Work
&lt;/h3&gt;

&lt;p&gt;Dart does not use shared-memory threads. Instead, it uses isolates, which are independent workers with their own memory heap. Heavy computations, like JSON parsing, image decoding, or data transformations, can be offloaded to a separate isolate without blocking the main UI thread. This is critical for maintaining 60 FPS even when the app is doing real work in the background.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Flutter Features That Directly Impact FPS
&lt;/h2&gt;

&lt;p&gt;When you hire Flutter developers who truly understand the framework, they will leverage these built-in tools to keep your app performant:&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Paint and Canvas API
&lt;/h3&gt;

&lt;p&gt;Flutter's &lt;code&gt;CustomPaint&lt;/code&gt; widget gives developers direct access to the Canvas API for drawing custom graphics. Unlike native approaches, which require bridging to native drawing APIs, Flutter's canvas runs in Dart and renders directly through the Impeller/Skia backend. This makes complex custom animations achievable at full frame rate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Animation System with Ticker-Based Scheduling
&lt;/h3&gt;

&lt;p&gt;Flutter's animation system is built around &lt;code&gt;Ticker&lt;/code&gt;, which synchronizes animations with the device's display refresh rate. Whether the device runs at 60 Hz or 120 Hz, Flutter animations automatically adapt. Developers use &lt;code&gt;AnimationController&lt;/code&gt;, &lt;code&gt;Tween&lt;/code&gt;, &lt;code&gt;CurvedAnimation&lt;/code&gt;, and the &lt;code&gt;flutter_animate&lt;/code&gt; package to build GPU-accelerated animations that stay smooth regardless of complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  ListView and Sliver-Based Scroll Performance
&lt;/h3&gt;

&lt;p&gt;Flutter's &lt;code&gt;ListView.builder&lt;/code&gt; constructs only the widgets currently visible on screen, lazily building and destroying widgets as the user scrolls. The Sliver system takes this further, allowing fine-grained control over how items are laid out and recycled. The result is smooth, jank-free scrolling even with thousands of items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image Caching and Decoding on Background Threads
&lt;/h3&gt;

&lt;p&gt;Flutter decodes images on a background isolate to avoid blocking the UI thread during image loading. Combined with packages like &lt;code&gt;cached_network_image&lt;/code&gt;, large image grids and feeds maintain smooth scrolling because the main thread is never waiting for disk or network I/O.&lt;/p&gt;

&lt;h3&gt;
  
  
  Raster and UI Thread Separation
&lt;/h3&gt;

&lt;p&gt;Flutter runs two main threads: the UI thread (Dart code) and the Raster thread (GPU commands). These threads operate in parallel. The UI thread computes the next frame while the Raster thread is still drawing the current one. This pipeline is a core reason why Flutter can sustain high frame rates without the main thread becoming a bottleneck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Performance Benchmarks: Flutter vs. The Competition
&lt;/h2&gt;

&lt;p&gt;Numerous independent benchmarks and real-world case studies have compared Flutter's rendering performance against React Native and native development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Startup Time:&lt;/strong&gt; Flutter apps compiled in AOT mode cold-start in comparable times to native apps, consistently faster than React Native apps that must initialize a JavaScript runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Animation Frame Rate:&lt;/strong&gt; In scroll and animation benchmarks, Flutter maintains 60 FPS on mid-range devices where React Native frequently drops to 45-50 FPS under the same workload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Usage:&lt;/strong&gt; Flutter's memory footprint is competitive with native apps. Because the framework controls its own widgets and rendering, there is less overhead from redundant UI abstraction layers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jank Rate:&lt;/strong&gt; With Impeller enabled on iOS and &lt;strong&gt;&lt;a href="https://www.zignuts.com/blog/android-16-17-adaptive-design-compose?utm_source=seo&amp;amp;utm_medium=backlinks&amp;amp;utm_campaign=seo_referral&amp;amp;utm_id=4" rel="noopener noreferrer"&gt;Android&lt;/a&gt;&lt;/strong&gt;, Flutter's jank rate (frames that miss their deadline) is measurably lower than alternatives, including some native implementations that use complex view hierarchies.&lt;/p&gt;

&lt;p&gt;Companies like &lt;strong&gt;Alibaba&lt;/strong&gt;, &lt;strong&gt;BMW&lt;/strong&gt;, &lt;strong&gt;eBay Motors&lt;/strong&gt;, &lt;strong&gt;Nubank&lt;/strong&gt;, and &lt;strong&gt;Google Pay&lt;/strong&gt; have all published performance improvements after migrating to or building with Flutter. Nubank, serving over 80 million customers, chose Flutter specifically because of its performance consistency across the wide range of Android devices popular in Latin America.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Skilled Flutter Developers Do Differently
&lt;/h2&gt;

&lt;p&gt;Knowing the framework is table stakes. What separates an average Flutter developer from a performance expert is the ability to diagnose and eliminate the subtle bottlenecks that accumulate in complex apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Profiling with Flutter DevTools
&lt;/h3&gt;

&lt;p&gt;Flutter DevTools provides a timeline view, a memory profiler, a widget rebuild tracker, and a network inspector. Expert Flutter developers routinely profile apps in profile mode (not debug mode) to identify slow frames, excessive widget rebuilds, and memory leaks. They know how to read flame charts and identify which function call is eating into the frame budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding Unnecessary Widget Rebuilds
&lt;/h3&gt;

&lt;p&gt;In Flutter, rebuilds are cheap, but not free. Developers who understand the &lt;code&gt;const&lt;/code&gt; keyword, &lt;code&gt;shouldRebuild&lt;/code&gt; in &lt;code&gt;InheritedWidget&lt;/code&gt;, selector patterns in state management libraries like Riverpod or BLoC, and splitting large widget trees into smaller, isolated components can dramatically reduce the number of widgets rebuilt on each frame.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing State Management for the UI Thread
&lt;/h3&gt;

&lt;p&gt;Poor state management choices can trigger full-tree rebuilds on every state change. Expert developers design state management architectures where only the specific widgets that depend on a changed value are rebuilt. Libraries like Riverpod with &lt;code&gt;select&lt;/code&gt;, BLoC with granular streams, and MobX with reactive computed values all help achieve this goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shader Warmup and Impeller Configuration
&lt;/h3&gt;

&lt;p&gt;On projects where shader jank is observed (usually in the first few seconds of a new animation), experienced developers implement shader warmup routines or migrate the project to Impeller. They also understand how to configure the &lt;code&gt;FlutterFragmentActivity&lt;/code&gt; and rendering backend settings for optimal performance on specific Android GPU vendors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Platform Channel Optimization
&lt;/h3&gt;

&lt;p&gt;When Flutter apps need to call native code through platform channels, novice developers may call these synchronously on the main thread, causing frame drops. Experts structure platform channel calls asynchronously, use MethodChannels efficiently, and where performance is critical, use Flutter's FFI (Foreign Function Interface) to call native C/C++ code with near-zero overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Business Case: Why You Should Hire Flutter Developers Instead of Going Native or Web
&lt;/h2&gt;

&lt;p&gt;Building two separate native apps (one for iOS, one for Android) requires two separate teams, two codebases, two release cycles, and twice the QA effort. The business cost is enormous.&lt;/p&gt;

&lt;p&gt;Flutter collapses this into a single codebase that delivers native-grade performance on both platforms, and increasingly on web, desktop, and embedded devices as well.&lt;/p&gt;

&lt;p&gt;Here is the business math:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development Speed:&lt;/strong&gt; A Flutter team can ship features approximately 30-40% faster than two separate native teams covering the same feature set, because the codebase is shared and the hot reload development loop is faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team Size:&lt;/strong&gt; One Flutter team replaces two platform-specific teams, cutting hiring, onboarding, and salary overhead significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Parity:&lt;/strong&gt; Flutter apps on both iOS and Android use the same rendering pipeline, meaning performance bugs and optimizations apply everywhere. There is no situation where Android performs great but iOS stutters because of a platform-specific UI quirk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Consistency:&lt;/strong&gt; Because Flutter draws its own widgets, pixel-perfect design consistency across platforms is achievable. Designers deliver one spec, and the app looks identical on every device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long-Term Maintainability:&lt;/strong&gt; A single codebase is easier to maintain, refactor, and scale. Technical debt accumulates in one place and is resolved once, not twice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Industries Where High-FPS Flutter Apps Make the Most Impact
&lt;/h2&gt;

&lt;p&gt;Not every app needs to obsess over frame rate. A simple form-based utility app will be fine at 45 FPS. But for these categories, frame rate is directly tied to revenue and user satisfaction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fintech and Trading Apps:&lt;/strong&gt; Real-time data visualization, animated charts, and live price feeds require smooth rendering. Dropped frames on a trading screen erode user trust instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gaming and Interactive Apps:&lt;/strong&gt; Casual games, AR experiences, and interactive storytelling apps built with Flutter and the Flame game engine depend entirely on sustained high FPS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E-Commerce and Retail:&lt;/strong&gt; Product image carousels, parallax scrolling hero sections, and gesture-driven filtering experiences must be smooth to convert browsers into buyers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Health and Fitness Apps:&lt;/strong&gt; Workout tracking dashboards, animated progress rings, and real-time sensor data visualizations require fluid UI to feel premium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Education and EdTech:&lt;/strong&gt; Interactive learning modules, animated explainers, and gamified progress systems benefit enormously from high frame rates because engagement drops with visual friction.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Hire Flutter Developers: What to Look For
&lt;/h2&gt;

&lt;p&gt;When you are ready to build a high-performance Flutter application, evaluating candidates on Flutter fundamentals alone is not enough. Here is what to assess:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Profiling Skills:&lt;/strong&gt; Can they use Flutter DevTools to identify a jank source? Ask them to walk you through how they would diagnose a dropped frame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State Management Depth:&lt;/strong&gt; Do they understand the trade-offs between Provider, Riverpod, BLoC, GetX, and MobX? Can they explain why one would cause more rebuilds than another?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dart Proficiency:&lt;/strong&gt; Are they comfortable with isolates, streams, async/await patterns, and Dart's sound null safety system?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native Integration Experience:&lt;/strong&gt; Have they worked with platform channels, FFI, or native plugins? High-performance apps often need to dip into native code for camera, sensors, or GPU operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portfolio and Production Experience:&lt;/strong&gt; Have they shipped apps to the Play Store or App Store that are actively used? Real production experience reveals how they handle release builds, CI/CD, crash reporting, and performance monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing Culture:&lt;/strong&gt; Do they write widget tests, integration tests, and golden tests? Performant apps stay performant when they have test coverage that catches regressions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Performance Is a Feature, Flutter Is the Engine
&lt;/h2&gt;

&lt;p&gt;The mobile landscape is unforgiving. Users expect applications to feel fast, responsive, and alive. Every frame that drops, every animation that stutters, every scroll that hitches is a signal to the user that your product is not polished enough to deserve their attention.&lt;/p&gt;

&lt;p&gt;Flutter, with its GPU-accelerated rendering engine, AOT-compiled Dart code, isolate-based concurrency, and rich performance tooling, is one of the most capable platforms available for building high-FPS mobile applications in 2025 and beyond. But the framework is only as powerful as the developers wielding it.&lt;/p&gt;

&lt;p&gt;When you invest the time and resources to hire Flutter developers who understand performance deeply, not just syntax and widgets, but profiling, state management architecture, rendering internals, and native integration, you get more than an app. You get a product that users enjoy using, recommend to others, and return to again and again.&lt;/p&gt;

&lt;p&gt;Performance is not an afterthought. It is a competitive advantage. Flutter is the engine. The right developers are the fuel.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you shipped a high-performance Flutter app? Share your performance wins or challenges in the comments below.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
