<?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>Forem: Mohammad Rajaei Monfared</title>
    <description>The latest articles on Forem by Mohammad Rajaei Monfared (@mrajaeim).</description>
    <link>https://forem.com/mrajaeim</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%2F697882%2F485e5eea-e5ff-4010-93c3-88634c92b475.png</url>
      <title>Forem: Mohammad Rajaei Monfared</title>
      <link>https://forem.com/mrajaeim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrajaeim"/>
    <language>en</language>
    <item>
      <title>🚖 Building a Scalable Frontend Mock Architecture with MSW, Factories, and Services (Uber-Like Example)</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Thu, 16 Oct 2025 21:30:01 +0000</pubDate>
      <link>https://forem.com/mrajaeim/building-a-scalable-frontend-mock-architecture-with-msw-factories-and-services-uber-like-3kgi</link>
      <guid>https://forem.com/mrajaeim/building-a-scalable-frontend-mock-architecture-with-msw-factories-and-services-uber-like-3kgi</guid>
      <description>&lt;p&gt;If you’ve ever built an app that depends on complex backend APIs — like a ride-sharing or delivery platform — you know the pain:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The backend isn’t ready yet… but I still need to test my UI, maps, and user flows.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Frontend developers often get stuck waiting for endpoints or using rigid JSON mocks that quickly become outdated.&lt;br&gt;
There’s a better way.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how to build a &lt;strong&gt;scalable mock architecture&lt;/strong&gt; for your frontend using &lt;strong&gt;Mock Service Worker (MSW)&lt;/strong&gt; — the modern way to simulate APIs directly in the browser or test environment.&lt;/p&gt;

&lt;p&gt;We’ll model a &lt;strong&gt;simplified Uber-like app&lt;/strong&gt; with entities like &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Drivers&lt;/code&gt;, &lt;code&gt;Vehicles&lt;/code&gt;, &lt;code&gt;Wallet&lt;/code&gt;, &lt;code&gt;MyLastTrips&lt;/code&gt;, and more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Note: The entities and examples here are simplified to illustrate the architecture.&lt;br&gt;
Real ride-sharing systems have more complex relationships and data flows.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  🧩 Why Traditional Mocks Don’t Scale
&lt;/h2&gt;

&lt;p&gt;Most frontend teams start with something simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mocks/handlers.ts&lt;/span&gt;
&lt;span class="nx"&gt;rest&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="s1"&gt;/api/drivers&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;req&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="nx"&gt;ctx&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="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&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="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.9&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;It works… until it doesn’t.&lt;br&gt;
When your app grows — filters, pagination, dynamic routes, price estimates, and user-specific logic — this flat mock structure becomes unmaintainable.&lt;/p&gt;

&lt;p&gt;The solution?&lt;br&gt;
Design your mocks like a &lt;strong&gt;real backend&lt;/strong&gt;, with clear layers and responsibilities.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗 The Layered Mock Architecture
&lt;/h2&gt;

&lt;p&gt;Here’s the folder structure we’ll use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  mocks/
    handlers/
      driversHandlers.ts
      ridesHandlers.ts
    factories/
      userFactory.ts
      driversFactory.ts
      vehiclesFactory.ts
      walletFactory.ts
      myLocationsFactory.ts
      myLastTripsFactory.ts
    generators/
      carLocationsGenerator.ts
      rideRequestsGenerator.ts
      priceEstimatesGenerator.ts
      routesGenerator.ts
    services/
      ridesService.ts
      driversService.ts
      walletService.ts
    browser.ts
    server.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer has a specific purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;factories/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Static seed data&lt;/td&gt;
&lt;td&gt;Acts as your “mock database”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generators/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dynamic or computed data&lt;/td&gt;
&lt;td&gt;Produces live, random, or rule-based data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;services/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Business logic&lt;/td&gt;
&lt;td&gt;Simulates backend operations (search, filters, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;handlers/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API interface&lt;/td&gt;
&lt;td&gt;Connects MSW routes to your mock services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧱 Step 1: Factories — The Mock Database
&lt;/h2&gt;

&lt;p&gt;Factories provide &lt;strong&gt;static, consistent seed data&lt;/strong&gt;.&lt;br&gt;
They act like an in-memory database for your mocks.&lt;/p&gt;

&lt;p&gt;Here’s a reusable base factory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// factories/BaseFactory.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseFactory&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;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;clone&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;structuredClone&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&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="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="nf"&gt;createMany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&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;item&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;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;createOne&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has no seed data`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&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;seed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, define your domain factories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// factories/driversFactory.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;BaseFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./BaseFactory&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;class&lt;/span&gt; &lt;span class="nc"&gt;DriversFactory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;vehicleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.9&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;vehicleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.7&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other factories might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UserFactory&lt;/code&gt; – the logged-in user data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VehiclesFactory&lt;/code&gt; – registered vehicles&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WalletFactory&lt;/code&gt; – balance and transactions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MyLocationsFactory&lt;/code&gt; – user’s saved addresses&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MyLastTripsFactory&lt;/code&gt; – trip history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Tip:&lt;/strong&gt; Keep this data simple and clean. It doesn’t need to be “real” — just realistic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 2: Generators — Dynamic or Computed Data
&lt;/h2&gt;

&lt;p&gt;Some data can’t be static. Think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A driver’s &lt;strong&gt;live location&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price estimates&lt;/strong&gt; that change with distance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes&lt;/strong&gt; generated from coordinates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where &lt;strong&gt;generators&lt;/strong&gt; come in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// generators/carLocationsGenerator.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;faker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@faker-js/faker&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;generateCarLocations&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;5&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="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;driverId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;min&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="na"&gt;max&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="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="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;You can build similar ones for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rideRequestsGenerator&lt;/code&gt; – mock incoming ride requests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;priceEstimatesGenerator&lt;/code&gt; – calculate approximate fares&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;routesGenerator&lt;/code&gt; – fake polyline routes between points&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;br&gt;
Generators make your mocks feel &lt;em&gt;alive&lt;/em&gt;, perfect for testing live maps, dynamic UI updates, or ride-status screens.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 Step 3: Services — Mock Backend Logic
&lt;/h2&gt;

&lt;p&gt;Services combine factories and generators into &lt;strong&gt;domain-specific logic&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/ridesService.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;MyLastTripsFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../factories/myLastTripsFactory&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;generateRideRequests&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generators/rideRequestsGenerator&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;generatePriceEstimates&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generators/priceEstimatesGenerator&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;class&lt;/span&gt; &lt;span class="nc"&gt;RidesService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trips&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;MyLastTripsFactory&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;createMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;listMyTrips&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trips&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;trip&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;trip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getActiveRideRequests&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;generateRideRequests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getPriceEstimate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&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;generatePriceEstimates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&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;Why it matters:&lt;/strong&gt;&lt;br&gt;
This mirrors how a real backend behaves — filtering, calculating, and combining data logically — not just serving static JSON.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌐 Step 4: Handlers — The MSW API Layer
&lt;/h2&gt;

&lt;p&gt;Now we wire everything together using &lt;strong&gt;Mock Service Worker (MSW)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// handlers/ridesHandlers.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;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw&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;RidesService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/ridesService&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;ridesService&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;RidesService&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;ridesHandlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;rest&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="s1"&gt;/api/trips&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;req&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="nx"&gt;ctx&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;userId&lt;/span&gt; &lt;span class="o"&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;req&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="nx"&gt;searchParams&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="s1"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;'&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ridesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listMyTrips&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&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="nx"&gt;ctx&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="nx"&gt;trips&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="nx"&gt;rest&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="s1"&gt;/api/price-estimate&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;req&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="nx"&gt;ctx&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;pickup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;searchParams&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="s1"&gt;pickup&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;dropoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;searchParams&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="s1"&gt;dropoff&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;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ridesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPriceEstimate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pickup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropoff&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;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&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="nx"&gt;ctx&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="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And connect it to your dev environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mocks/browser.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;setupWorker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw&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;ridesHandlers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./handlers/ridesHandlers&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;driversHandlers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./handlers/driversHandlers&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;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setupWorker&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;ridesHandlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;driversHandlers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it automatically in dev mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&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;worker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mocks/browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;onUnhandledRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bypass&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;h2&gt;
  
  
  🧰 Bonus: Works in Tests and Storybook Too
&lt;/h2&gt;

&lt;p&gt;This architecture is not just for local development — it also powers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit/Integration Tests&lt;/strong&gt; (via &lt;code&gt;setupServer&lt;/code&gt; from &lt;code&gt;msw/node&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storybook&lt;/strong&gt; (via &lt;code&gt;msw-storybook-addon&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End Prototyping&lt;/strong&gt; without a real backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Storybook config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mswDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw-storybook-addon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;initialize&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;decorators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mswDecorator&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌱 Why This Architecture Works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🧩 &lt;strong&gt;Separation of Concerns&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Each layer (factory, generator, service) does one job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚙️ &lt;strong&gt;Backend-Like Simulation&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Services handle filtering, routes, and price logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔁 &lt;strong&gt;Reusability&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Works in dev, tests, and Storybook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💡 &lt;strong&gt;Flexibility&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Add or override scenarios easily (e.g., surge pricing, no drivers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧱 &lt;strong&gt;Maintainability&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Add new entities (e.g., Wallet, Vehicles) without rewriting mocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;This architecture gives you &lt;strong&gt;production-like realism&lt;/strong&gt; without depending on real APIs.&lt;br&gt;
Your frontend becomes faster to develop, test, and demo — even before the backend exists.&lt;/p&gt;

&lt;p&gt;By organizing your mocks into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧱 &lt;strong&gt;Factories&lt;/strong&gt; (static seeds)&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Generators&lt;/strong&gt; (dynamic data)&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Services&lt;/strong&gt; (logic layer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and connecting them through MSW handlers, you create a &lt;strong&gt;self-contained virtual backend&lt;/strong&gt; for your app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example used Uber-like entities such as &lt;em&gt;Drivers&lt;/em&gt;, &lt;em&gt;Vehicles&lt;/em&gt;, &lt;em&gt;MyLocations&lt;/em&gt;, &lt;em&gt;Wallet&lt;/em&gt;, and &lt;em&gt;RideRequests&lt;/em&gt;, but the same pattern applies to any complex domain — e-commerce, fintech, IoT, you name it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Click the links below to follow me on all platforms:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>A Guide to Modern Browser Storage And Data Sharing Capabilities</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Thu, 16 Oct 2025 20:54:50 +0000</pubDate>
      <link>https://forem.com/mrajaeim/a-guide-to-modern-browser-storage-and-data-sharing-capabilities-4eb8</link>
      <guid>https://forem.com/mrajaeim/a-guide-to-modern-browser-storage-and-data-sharing-capabilities-4eb8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Choosing the right browser storage can make or break your app's performance and security—here's how to get it right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the early days of the web, browsers were simple document viewers. Today, they are powerful application platforms. Modern web apps often feel as responsive and capable as their native counterparts, and a key reason for this is their ability to store data directly on the client-side. But with great power comes great responsibility. The choice of where and how you store data in the browser has profound implications for your application's user experience, security, and overall performance.&lt;/p&gt;

&lt;p&gt;It's a common pitfall to reach for a familiar tool like &lt;code&gt;localStorage&lt;/code&gt; for every problem, but not all storage mechanisms are created equal. Some are synchronous, blocking the main thread and creating a janky user experience. Others are asynchronous and scalable but come with a steeper learning curve. Some are vulnerable to cross-site scripting (XSS) attacks, while others offer a more secure, sandboxed environment. Making the wrong choice can lead to anything from a sluggish UI to a critical security breach.&lt;/p&gt;

&lt;p&gt;This article is a practical guide to navigating the complex landscape of modern browser storage. We'll move beyond the familiar &lt;code&gt;localStorage&lt;/code&gt; and explore the full spectrum of tools at your disposal, including &lt;code&gt;SessionStorage&lt;/code&gt;, &lt;code&gt;Cookies&lt;/code&gt;, &lt;code&gt;IndexedDB&lt;/code&gt;, &lt;code&gt;Service Workers&lt;/code&gt;, and more. For each, we'll analyze the critical trade-offs between performance and security, and establish clear best practices. By the end, you'll be equipped to choose the right storage for the right job, building faster, more secure, and more reliable web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
The Classics: localstorage, sessionstorage, and cookies

&lt;ul&gt;
&lt;li&gt;LocalStorage: The Persistent Key-Value Store&lt;/li&gt;
&lt;li&gt;SessionStorage: The Tab-Specific Store&lt;/li&gt;
&lt;li&gt;Cookies: The Server's Messenger&lt;/li&gt;
&lt;li&gt;Quick Comparison: The Classics&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The Modern Powerhouse: raw-indexeddb-endraw

&lt;ul&gt;
&lt;li&gt;Performance: Asynchronous and Scalable&lt;/li&gt;
&lt;li&gt;Security: Origin-Isolated with Potential for More&lt;/li&gt;
&lt;li&gt;The Catch: A Complex API&lt;/li&gt;
&lt;li&gt;Best Practices: Use a Wrapper!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Specialized Tools for Specific Jobs

&lt;ul&gt;
&lt;li&gt;In-Memory Storage: The Need for Speed&lt;/li&gt;
&lt;li&gt;URL Query Parameters: The Shareable State&lt;/li&gt;
&lt;li&gt;BroadcastChannel API: The Cross-Tab Communicator&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Powering Offline Experiences: Service Workers and the Cache API

&lt;ul&gt;
&lt;li&gt;The Service Worker: Your App's Network Proxy&lt;/li&gt;
&lt;li&gt;The Cache API: The Service Worker's Storage&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Tying It All Together: Comparison and Best Practices

&lt;ul&gt;
&lt;li&gt;At a Glance: A Comparison of Browser Storage&lt;/li&gt;
&lt;li&gt;Unified Best Practices&lt;/li&gt;
&lt;li&gt;Key Takeaways&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion: Build Smarter, Not Harder&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Classics: &lt;code&gt;LocalStorage&lt;/code&gt;, &lt;code&gt;SessionStorage&lt;/code&gt;, and &lt;code&gt;Cookies&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before we dive into the heavy-duty storage solutions, let's revisit the three tools that have been the bedrock of browser data persistence for years. While still useful in specific scenarios, their limitations are what drove the need for more modern APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;LocalStorage&lt;/code&gt;: The Persistent Key-Value Store
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;LocalStorage&lt;/code&gt; is often the first tool developers reach for when they need to save data across browser sessions. It offers a simple, synchronous API for storing key-value pairs as strings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: The biggest drawback of &lt;code&gt;LocalStorage&lt;/code&gt; is its &lt;strong&gt;synchronous API&lt;/strong&gt;. Every read or write operation blocks the main thread, which can lead to a frozen UI if you're working with large amounts of data. With a typical limit of 5-10 MB, it's easy to run into performance bottlenecks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Data in &lt;code&gt;LocalStorage&lt;/code&gt; is accessible to any JavaScript running on the same origin. This makes it a prime target for &lt;strong&gt;Cross-Site Scripting (XSS) attacks&lt;/strong&gt;. If a malicious script finds its way onto your page, it can read everything in &lt;code&gt;LocalStorage&lt;/code&gt;. For this reason, you should &lt;strong&gt;never store sensitive information&lt;/strong&gt; like JWTs, API keys, or personal user data here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Non-sensitive, infrequently updated data, such as user interface preferences (like a theme choice) or remembering that a welcome modal has been closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SessionStorage&lt;/code&gt;: The Tab-Specific Store
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SessionStorage&lt;/code&gt; is nearly identical to &lt;code&gt;LocalStorage&lt;/code&gt; in its API, with one critical difference: its scope. Data stored in &lt;code&gt;SessionStorage&lt;/code&gt; is isolated to the current browser tab and is cleared the moment the tab is closed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance &amp;amp; Security&lt;/strong&gt;: It shares the same synchronous, blocking API and XSS vulnerabilities as &lt;code&gt;LocalStorage&lt;/code&gt;. The tab-specific isolation provides a minor security benefit by preventing scripts in other tabs from accessing the data, but the core risks remain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Storing transient data related to a single user session within one tab. A classic example is saving partially filled form data to prevent loss on an accidental reload.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Cookies&lt;/code&gt;: The Server's Messenger
&lt;/h3&gt;

&lt;p&gt;Unlike &lt;code&gt;LocalStorage&lt;/code&gt; and &lt;code&gt;SessionStorage&lt;/code&gt;, cookies were designed primarily for server-client communication, not client-side storage. They are automatically sent with every HTTP request to the same domain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Because they are attached to every request, large cookies can bloat request headers and slow down your application. Their small size limit (around 4KB) also makes them unsuitable for storing any significant amount of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Cookies are the traditional way to manage user sessions, but they come with their own set of security risks, most notably &lt;strong&gt;Cross-Site Request Forgery (CSRF)&lt;/strong&gt;. To mitigate this, modern applications must use the &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, and &lt;code&gt;SameSite=Strict&lt;/code&gt; attributes. The &lt;code&gt;HttpOnly&lt;/code&gt; flag is particularly important, as it makes the cookie inaccessible to JavaScript, providing a strong defense against XSS-based token theft.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Storing server-issued session identifiers. Use them for authentication tokens, but keep them small and secure them with the right flags. Avoid using them as a general-purpose data store.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick Comparison: The Classics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;LocalStorage&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;SessionStorage&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Cookies&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Until cleared by user&lt;/td&gt;
&lt;td&gt;Per tab/session&lt;/td&gt;
&lt;td&gt;Expires or session-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Origin-wide&lt;/td&gt;
&lt;td&gt;Tab-specific&lt;/td&gt;
&lt;td&gt;Domain/path specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Synchronous&lt;/td&gt;
&lt;td&gt;Synchronous&lt;/td&gt;
&lt;td&gt;N/A (sent via HTTP headers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~5-10 MB&lt;/td&gt;
&lt;td&gt;~5 MB&lt;/td&gt;
&lt;td&gt;~4 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High XSS risk&lt;/td&gt;
&lt;td&gt;High XSS risk&lt;/td&gt;
&lt;td&gt;CSRF/XSS risk (mitigable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UI preferences&lt;/td&gt;
&lt;td&gt;Temporary form data&lt;/td&gt;
&lt;td&gt;Server authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Modern Powerhouse: &lt;code&gt;IndexedDB&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When your application's storage needs grow beyond simple key-value pairs, or when the performance cost of &lt;code&gt;LocalStorage&lt;/code&gt; becomes too high, it's time to turn to &lt;code&gt;IndexedDB&lt;/code&gt;. This is a true client-side database, offering capabilities far beyond the simple storage mechanisms we've discussed so far.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IndexedDB&lt;/code&gt; is a low-level API for client-side storage of significant amounts of structured data, including files/blobs. It's the browser's answer to the limitations of &lt;code&gt;LocalStorage&lt;/code&gt; and is the foundation for most modern, data-intensive web applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance: Asynchronous and Scalable
&lt;/h3&gt;

&lt;p&gt;The single most important feature of &lt;code&gt;IndexedDB&lt;/code&gt; is its &lt;strong&gt;asynchronous API&lt;/strong&gt;. Unlike &lt;code&gt;LocalStorage&lt;/code&gt;, operations in &lt;code&gt;IndexedDB&lt;/code&gt; do not block the main thread. This means you can read or write large amounts of data without freezing the user interface, resulting in a smooth and responsive application. It's designed for scale, with storage limits typically in the hundreds of megabytes or even gigabytes, depending on the browser and available disk space.&lt;/p&gt;

&lt;p&gt;Furthermore, &lt;code&gt;IndexedDB&lt;/code&gt; stores structured data—JavaScript objects—natively. This means you don't have the overhead of serializing and deserializing JSON for every operation, which can be a significant performance gain in applications with frequent data access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security: Origin-Isolated with Potential for More
&lt;/h3&gt;

&lt;p&gt;Like other browser storage, &lt;code&gt;IndexedDB&lt;/code&gt; is isolated by origin, which prevents other websites from accessing your data. However, it is still accessible to any JavaScript running on your page, which means it's vulnerable to XSS attacks if your application has a security flaw. &lt;/p&gt;

&lt;p&gt;For sensitive data, the best practice is to add a layer of client-side encryption. You can use the built-in &lt;code&gt;Web Crypto API&lt;/code&gt; to encrypt data before you store it in &lt;code&gt;IndexedDB&lt;/code&gt;, ensuring that even if an attacker gains access to the database, the data remains unreadable.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Catch: A Complex API
&lt;/h3&gt;

&lt;p&gt;With great power comes... a more complex API. The native &lt;code&gt;IndexedDB&lt;/code&gt; API is event-based and requires you to manage transactions, versioning, and schemas manually. It can be cumbersome to work with directly, which has led to the development of several excellent wrapper libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices: Use a Wrapper!
&lt;/h3&gt;

&lt;p&gt;For almost all use cases, it's highly recommended to use a library like &lt;strong&gt;&lt;code&gt;Dexie.js&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;idb&lt;/code&gt;&lt;/strong&gt;. These wrappers provide a clean, modern, &lt;code&gt;Promise&lt;/code&gt;-based API that handles the underlying complexity of &lt;code&gt;IndexedDB&lt;/code&gt; transactions and schema management. They make working with &lt;code&gt;IndexedDB&lt;/code&gt; feel almost as simple as working with &lt;code&gt;LocalStorage&lt;/code&gt;, while retaining all of its performance benefits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best For&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applications that need to store large amounts of structured data.&lt;/li&gt;
&lt;li&gt;Offline-first Progressive Web Apps (PWAs).&lt;/li&gt;
&lt;li&gt;Caching complex API responses to reduce network requests.&lt;/li&gt;
&lt;li&gt;Any scenario where the synchronous nature of &lt;code&gt;LocalStorage&lt;/code&gt; would cause performance issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Specialized Tools for Specific Jobs
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;IndexedDB&lt;/code&gt; is the champion of large-scale persistent storage, not all data needs to be stored in a database. Sometimes you need the fastest possible access for temporary data, a way to share state in a URL, or a method to communicate between open tabs. For these jobs, we have a set of specialized tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  In-Memory Storage: The Need for Speed
&lt;/h3&gt;

&lt;p&gt;Not all data needs to survive a page refresh. The fastest storage available is the computer's RAM, which you can access directly by storing data in JavaScript variables or more structured state management solutions like Redux or Zustand stores.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Unbeatable. Access is nearly instantaneous, with no serialization overhead. This is where your application's active state should live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Persistence&lt;/strong&gt;: Being volatile is its key feature. Since the data is wiped on every page load, the security exposure is minimal. It's perfect for data that is fetched and used in a single session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Caching frequently accessed data that can be easily re-fetched, managing the real-time state of your UI, and holding temporary data that doesn't need to be persisted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  URL Query Parameters: The Shareable State
&lt;/h3&gt;

&lt;p&gt;Sometimes, the state of your application needs to be shareable. Think of applying a set of filters on an e-commerce site and wanting to send the results to a friend. This is the perfect use case for URL query parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: There's no real I/O cost, but be mindful of URL length limits (generally around 2000 characters), as excessively long URLs can cause issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: This is the most public form of state. The data is visible in the user's browser history, server logs, and to anyone they share the link with. &lt;strong&gt;Never, ever put sensitive information in a URL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Small, non-sensitive pieces of data that make a page's state shareable and bookmarkable, such as search queries, filter settings, or pagination info (&lt;code&gt;?page=2&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;BroadcastChannel&lt;/code&gt; API: The Cross-Tab Communicator
&lt;/h3&gt;

&lt;p&gt;What happens when a user logs out in one tab? Ideally, they should be logged out in all other open tabs of your application as well. This is the problem the &lt;code&gt;BroadcastChannel&lt;/code&gt; API was designed to solve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: It's a lightweight, event-driven API that allows different browser tabs, windows, or iframes of the same origin to send and receive messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Channels are scoped to a single origin, but any script on that origin can listen in. Therefore, you should never broadcast sensitive data. Instead, send simple signals or notifications, like "user-logged-out" or "theme-changed-to-dark".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best For&lt;/strong&gt;: Syncing state across multiple open tabs. It's the modern, efficient way to ensure a consistent user experience, especially for actions like authentication, theme changes, or real-time notifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For more detailed information, please visit &lt;a href="https://medium.com/@mrajaeim/understanding-window-postmessage-and-window-parent-postmessage-in-javascript-f09d4eac68ba" rel="noopener noreferrer"&gt;Mastering Cross-Window Communication in JavaScript: postMessage vs BroadcastChannel Explained&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Powering Offline Experiences: Service Workers and the Cache API
&lt;/h2&gt;

&lt;p&gt;What truly separates a modern web app from a traditional website is the ability to function without a network connection. This is the domain of the &lt;strong&gt;Service Worker&lt;/strong&gt;, a powerful technology that acts as a programmable proxy between your application, the browser, and the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Service Worker: Your App's Network Proxy
&lt;/h3&gt;

&lt;p&gt;A Service Worker is a type of Web Worker that runs on a separate thread from your main application. It can intercept and handle network requests, manage a cache of responses, and enable push notifications. Because it runs independently of your UI, it can continue to work even when the user has closed the application's tab, enabling features like background sync.&lt;/p&gt;

&lt;p&gt;Service Workers are the cornerstone of Progressive Web Apps (PWAs), allowing them to provide a reliable, app-like experience even on a flaky network connection or when completely offline.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;Cache API&lt;/code&gt;: The Service Worker's Storage
&lt;/h3&gt;

&lt;p&gt;While a Service Worker can use &lt;code&gt;IndexedDB&lt;/code&gt;, its primary storage tool is the &lt;strong&gt;&lt;code&gt;Cache API&lt;/code&gt;&lt;/strong&gt;. This is a specialized storage mechanism designed for holding HTTP request and response pairs. It allows you to programmatically save network responses and serve them directly from the cache, bypassing the network entirely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: The performance implications are massive. By serving assets and API responses from the cache, you can make your application load almost instantly on repeat visits. Caching strategies like &lt;code&gt;stale-while-revalidate&lt;/code&gt; (serving from the cache while fetching an update in the background) provide the perfect balance of speed and freshness.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Service Workers are highly secure. They can only be registered on pages served over &lt;strong&gt;HTTPS&lt;/strong&gt;, which prevents man-in-the-middle attacks. They run in a sandboxed environment and have no direct access to the DOM, which limits their exposure to XSS attacks. However, you must still be careful not to cache sensitive, user-specific data, as the cache is persistent and could be accessed if the application's security is compromised.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Best For&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating offline-first applications.&lt;/li&gt;
&lt;li&gt;Caching application shell assets (HTML, CSS, JS) for instant loading.&lt;/li&gt;
&lt;li&gt;Caching API responses to reduce network dependency and improve perceived performance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tying It All Together: Comparison and Best Practices
&lt;/h2&gt;

&lt;p&gt;We've explored a wide range of browser storage options, each with its own strengths and weaknesses. Choosing the right one depends on a careful balance of performance, security, and persistence requirements. To make this easier, let's summarize our findings.&lt;/p&gt;

&lt;h3&gt;
  
  
  At a Glance: A Comparison of Browser Storage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Security Level&lt;/th&gt;
&lt;th&gt;Performance Impact&lt;/th&gt;
&lt;th&gt;Persistence&lt;/th&gt;
&lt;th&gt;Size Limit&lt;/th&gt;
&lt;th&gt;Async&lt;/th&gt;
&lt;th&gt;Typical Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;In-Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Secure (Volatile)&lt;/td&gt;
&lt;td&gt;⚡ Fastest&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;RAM Limit&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Temporary UI State&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LocalStorage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ High XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Blocking I/O&lt;/td&gt;
&lt;td&gt;✅ Permanent&lt;/td&gt;
&lt;td&gt;~5MB&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Non-sensitive Preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SessionStorage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ High XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Blocking I/O&lt;/td&gt;
&lt;td&gt;⚪ Per Tab&lt;/td&gt;
&lt;td&gt;~5MB&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Single-tab Session Data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cookies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ CSRF/XSS Risk&lt;/td&gt;
&lt;td&gt;🚫 Slows HTTP&lt;/td&gt;
&lt;td&gt;✅ Expires&lt;/td&gt;
&lt;td&gt;~4KB&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Server Session Tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IndexedDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚪ XSS Risk (Encrypt!)&lt;/td&gt;
&lt;td&gt;✅ Async, Scalable&lt;/td&gt;
&lt;td&gt;✅ Permanent&lt;/td&gt;
&lt;td&gt;100MB+&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Large/Structured Data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cache API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sandboxed (HTTPS)&lt;/td&gt;
&lt;td&gt;✅ Async, Fast&lt;/td&gt;
&lt;td&gt;✅ Evictable&lt;/td&gt;
&lt;td&gt;Large&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Offline Assets &amp;amp; Responses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;URL Params&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Publicly Visible&lt;/td&gt;
&lt;td&gt;⚡ Light&lt;/td&gt;
&lt;td&gt;⚪ Shareable&lt;/td&gt;
&lt;td&gt;~2KB&lt;/td&gt;
&lt;td&gt;✅ N/A&lt;/td&gt;
&lt;td&gt;Shareable Filter State&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BroadcastChannel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Cross-tab Exposure&lt;/td&gt;
&lt;td&gt;⚡ Fast (Events)&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Cross-tab Syncing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Unified Best Practices
&lt;/h3&gt;

&lt;p&gt;Regardless of the tool you choose, a few universal principles will help you build more secure and performant applications.&lt;/p&gt;

&lt;h4&gt;
  
  
  🧱 Security Principles
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never Store Sensitive Data in Client-Accessible Storage&lt;/strong&gt;: This includes JWTs, API keys, passwords, or personal information. &lt;code&gt;LocalStorage&lt;/code&gt;, &lt;code&gt;SessionStorage&lt;/code&gt;, and &lt;code&gt;IndexedDB&lt;/code&gt; are all readable by any JavaScript on the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;HttpOnly&lt;/code&gt; Cookies for Auth Tokens&lt;/strong&gt;: This is the single most effective defense against token theft via XSS, as it makes the cookie inaccessible to JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypt Sensitive Local Data&lt;/strong&gt;: If you must store sensitive information client-side (e.g., in &lt;code&gt;IndexedDB&lt;/code&gt; for an offline app), use the &lt;code&gt;Web Crypto API&lt;/code&gt; to encrypt it first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assume All Client-Side Data Can Be Manipulated&lt;/strong&gt;: Always validate data on the server before processing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚡ Performance Principles
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async Over Sync&lt;/strong&gt;: Always prefer asynchronous APIs like &lt;code&gt;IndexedDB&lt;/code&gt; and the &lt;code&gt;Cache API&lt;/code&gt; over synchronous ones like &lt;code&gt;LocalStorage&lt;/code&gt; to avoid blocking the main thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Load Your Data&lt;/strong&gt;: Don't eagerly load large amounts of data into storage. Fetch and cache it as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use In-Memory for Hot Data&lt;/strong&gt;: For data that is accessed frequently, keep it in an in-memory state variable for the fastest possible access. Persist it to storage only when necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Mindful of Quotas&lt;/strong&gt;: Monitor storage usage with &lt;code&gt;navigator.storage.estimate()&lt;/code&gt; and be prepared to handle quota errors gracefully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;LocalStorage&lt;/code&gt; is not your default&lt;/strong&gt;: Its synchronous nature and security risks make it a poor choice for anything but the simplest, non-sensitive data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;IndexedDB&lt;/code&gt; is the modern standard&lt;/strong&gt;: For any significant amount of client-side data, &lt;code&gt;IndexedDB&lt;/code&gt; (used with a wrapper like &lt;code&gt;Dexie.js&lt;/code&gt;) is the best choice for performance and scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;HttpOnly&lt;/code&gt; cookies are for authentication&lt;/strong&gt;: They are the most secure place to store session tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Workers are for offline&lt;/strong&gt;: The &lt;code&gt;Cache API&lt;/code&gt; combined with a Service Worker is the key to building reliable, offline-first applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security is paramount&lt;/strong&gt;: Never trust the client. Encrypt sensitive data and use &lt;code&gt;HttpOnly&lt;/code&gt; cookies for authentication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion: Build Smarter, Not Harder
&lt;/h2&gt;

&lt;p&gt;The landscape of browser storage is far richer and more nuanced than just &lt;code&gt;localStorage&lt;/code&gt;. Choosing the right storage solution is not about finding a single tool that does everything; it's about understanding the trade-offs and composing a strategy that fits your application's unique needs. The modern web is built on a foundation of smart, hybrid approaches.&lt;/p&gt;

&lt;p&gt;An application might use &lt;code&gt;HttpOnly&lt;/code&gt; cookies for authentication, &lt;code&gt;IndexedDB&lt;/code&gt; to store complex data for offline use, in-memory variables for real-time UI state, and the &lt;code&gt;BroadcastChannel&lt;/code&gt; API to keep multiple tabs in sync. This is not over-engineering; it's a sign of a mature, robust architecture.&lt;/p&gt;

&lt;p&gt;As browsers continue to evolve, the trend is clear: we are moving towards more secure, asynchronous, and origin-isolated storage models. By embracing these modern APIs and understanding their underlying principles, you can build the next generation of web applications—apps that are not only fast and feature-rich but also secure and reliable, no matter the user's device or network condition. The power is in your hands; it's time to build smarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊
&lt;/h2&gt;

&lt;p&gt;Your support and engagement mean the world to me.&lt;br&gt;&lt;br&gt;
Let's create a community of knowledge enthusiasts and professionals striving for excellence and continuous learning.  &lt;/p&gt;

&lt;p&gt;Click the links below to follow me on all platforms:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;#WebSecurity&lt;/code&gt; &lt;code&gt;#WebPerformance&lt;/code&gt; &lt;code&gt;#WebDevelopment&lt;/code&gt; &lt;code&gt;#BrowserAPIs&lt;/code&gt; &lt;code&gt;#Frontend&lt;/code&gt; &lt;code&gt;#JavaScript&lt;/code&gt; &lt;code&gt;#IndexedDB&lt;/code&gt; &lt;code&gt;#Cookies&lt;/code&gt; &lt;code&gt;#LocalStorage&lt;/code&gt; &lt;code&gt;#PWAs&lt;/code&gt; &lt;code&gt;#WebDevTips&lt;/code&gt;&lt;/p&gt;

</description>
      <category>websecurity</category>
      <category>webperf</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Ultimate Guide to Mastering `useEffect`</title>
      <dc:creator>Mohammad Rajaei Monfared</dc:creator>
      <pubDate>Wed, 15 Oct 2025 14:24:38 +0000</pubDate>
      <link>https://forem.com/mrajaeim/the-ultimate-guide-to-mastering-useeffect-1ci9</link>
      <guid>https://forem.com/mrajaeim/the-ultimate-guide-to-mastering-useeffect-1ci9</guid>
      <description>&lt;p&gt;From lifecycle chaos to declarative harmony, this guide demystifies React's most powerful Hook.&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; Hook is arguably one of the most important yet misunderstood parts of modern React. For developers coming from class-based components, it feels like a strange new paradigm. For newcomers, it can seem like a magic box where you put any code that "doesn't fit" in the render. But &lt;code&gt;useEffect&lt;/code&gt; is far more than that—it's a precise tool for synchronizing your component with external systems.&lt;/p&gt;

&lt;p&gt;This guide breaks down everything you need to know, from the fundamentals of component lifecycles to advanced patterns and common pitfalls. By the end, you'll not only understand &lt;em&gt;how&lt;/em&gt; &lt;code&gt;useEffect&lt;/code&gt; works but also &lt;em&gt;why&lt;/em&gt; it was designed and &lt;em&gt;when&lt;/em&gt; to use it effectively. Let's dive in and transform &lt;code&gt;useEffect&lt;/code&gt; from a source of confusion into your most reliable ally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
1. Understanding the React Component Lifecycle

&lt;ul&gt;
&lt;li&gt;Before Hooks: The Classic Lifecycle Methods&lt;/li&gt;
&lt;li&gt;After Hooks: &lt;code&gt;useEffect&lt;/code&gt; Unifies the Lifecycle&lt;/li&gt;
&lt;li&gt;A Visual Timeline of the Functional Component Lifecycle&lt;/li&gt;
&lt;li&gt;Why Was &lt;code&gt;useEffect&lt;/code&gt; Introduced?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

2. The Purpose of &lt;code&gt;useEffect&lt;/code&gt; — What It Really Does

&lt;ul&gt;
&lt;li&gt;Common Examples of Side Effects&lt;/li&gt;
&lt;li&gt;It Runs After the Paint&lt;/li&gt;
&lt;li&gt;Misconception: It’s Not for All Logic&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

3. The Dependencies Array Demystified

&lt;ul&gt;
&lt;li&gt;The Three Modes of &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How React Compares Dependencies&lt;/li&gt;
&lt;li&gt;How to Fix Shallow Comparison Issues&lt;/li&gt;
&lt;li&gt;Tips to Avoid Common Pitfalls&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

4. Cleanup Functions and the “Return” Mystery

&lt;ul&gt;
&lt;li&gt;Why &lt;code&gt;useEffect&lt;/code&gt; Can Return a Function&lt;/li&gt;
&lt;li&gt;When Does the Cleanup Function Run?&lt;/li&gt;
&lt;li&gt;Real-World Cases for Cleanup&lt;/li&gt;
&lt;li&gt;Why Cleanup Prevents Memory Leaks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

5. Multiple &lt;code&gt;useEffect&lt;/code&gt;s: Execution and Cleanup Order

&lt;ul&gt;
&lt;li&gt;Execution Order: Top to Bottom&lt;/li&gt;
&lt;li&gt;Cleanup Order: Bottom to Top (Reverse Order)&lt;/li&gt;
&lt;li&gt;Why Splitting Concerns is Cleaner&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

6. Debugging &lt;code&gt;useEffect&lt;/code&gt; Like a Pro

&lt;ul&gt;
&lt;li&gt;Common Pitfalls and How to Spot Them&lt;/li&gt;
&lt;li&gt;Use the ESLint Rule (and When to Ignore It)&lt;/li&gt;
&lt;li&gt;Tracing with Logs and Custom Hooks&lt;/li&gt;
&lt;li&gt;React DevTools Profiler&lt;/li&gt;
&lt;li&gt;Tips: &lt;code&gt;useRef&lt;/code&gt; for Tracking&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

7. When Not to Use &lt;code&gt;useEffect&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Anti-Pattern: Unnecessary State Mirroring&lt;/li&gt;
&lt;li&gt;Anti-Pattern: Computations and Derived State&lt;/li&gt;
&lt;li&gt;Prefer Event Handlers for User Actions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

8. Practical Examples &amp;amp; Patterns

&lt;ul&gt;
&lt;li&gt;Pattern: Data Fetching with &lt;code&gt;AbortController&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pattern: Syncing the Browser Tab Title&lt;/li&gt;
&lt;li&gt;Pattern: Custom Hooks Abstraction (e.g., &lt;code&gt;useLocalStorage&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

9. Wrap-Up

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; Cheat Sheet&lt;/li&gt;
&lt;li&gt;Visual Summary&lt;/li&gt;
&lt;li&gt;The Future of Effects&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Understanding the React Component Lifecycle
&lt;/h2&gt;

&lt;p&gt;Before we can master &lt;code&gt;useEffect&lt;/code&gt;, we need to travel back in time to the era of class components. The component lifecycle was a set of distinct methods that gave us hooks into a component's life, from birth to death.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Hooks: The Classic Lifecycle Methods
&lt;/h3&gt;

&lt;p&gt;In class components, side effects like fetching data, setting up subscriptions, or manually changing the DOM were handled by specific lifecycle methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidMount()&lt;/code&gt;&lt;/strong&gt;: Fired only once, immediately after the component is mounted (inserted into the tree). This was the perfect place for initial data fetches or setting up subscriptions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidUpdate(prevProps, prevState)&lt;/code&gt;&lt;/strong&gt;: Called on every re-render, but not for the initial render. Logic here often required checking if props or state had changed to avoid unnecessary re-fetches.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentWillUnmount()&lt;/code&gt;&lt;/strong&gt;: Called right before the component is destroyed. This was the place to clean up subscriptions, timers, or any other lingering side effects to prevent memory leaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation often led to related logic being split across different methods, making components harder to follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  After Hooks: &lt;code&gt;useEffect&lt;/code&gt; Unifies the Lifecycle
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; Hook simplifies this by unifying these concepts into a single API. It runs &lt;em&gt;after&lt;/em&gt; React renders the component, allowing you to perform side effects without blocking the browser paint.&lt;/p&gt;

&lt;p&gt;Here’s how it maps to the old lifecycle methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidMount&lt;/code&gt;&lt;/strong&gt;: An effect with an empty dependency array (&lt;code&gt;[]&lt;/code&gt;) runs only once, after the initial render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentDidUpdate&lt;/code&gt;&lt;/strong&gt;: An effect with dependencies in its array (&lt;code&gt;[prop, state]&lt;/code&gt;) runs after the initial render and any time those dependencies change.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;componentWillUnmount&lt;/code&gt;&lt;/strong&gt;: The cleanup function returned from an effect serves this purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This new model encourages you to group related logic together, not by lifecycle event, but by &lt;strong&gt;concern&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Visual Timeline of the Functional Component Lifecycle
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogdi2xc66acroyfqmgdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogdi2xc66acroyfqmgdg.png" alt=" " width="523" height="637"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Was &lt;code&gt;useEffect&lt;/code&gt; Introduced?
&lt;/h3&gt;

&lt;p&gt;The shift to Hooks wasn't just for a cleaner syntax. It solved fundamental problems with class components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Separation of Concerns&lt;/strong&gt;: In classes, a single &lt;code&gt;componentDidMount&lt;/code&gt; might contain logic for data fetching, setting up event listeners, and logging. &lt;code&gt;useEffect&lt;/code&gt; allows you to split these into separate, independent effects. Each effect handles one concern, making the code more modular and readable.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Declarative Side Effects&lt;/strong&gt;: Instead of issuing imperative commands at different points in time (&lt;code&gt;mount&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;), you &lt;em&gt;declare&lt;/em&gt; the side effects that should be synchronized with your component's state. You tell React, “When this data changes, run this effect.” React handles the when and how, making your code less error-prone and easier to reason about.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  2. The Purpose of &lt;code&gt;useEffect&lt;/code&gt; — What It Really Does
&lt;/h2&gt;

&lt;p&gt;The official React documentation defines &lt;code&gt;useEffect&lt;/code&gt; as a way to perform side effects in function components. But what exactly is a “side effect”?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; A side effect is any interaction with the “outside world” that occurs outside of a component’s render. If your component is a pure function, its only job is to return JSX based on its props and state. Anything else is a side effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Examples of Side Effects
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is your go-to tool for managing these interactions. Here are the most common use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Fetching data from an API&lt;/strong&gt;: Retrieving remote data and updating component state.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Setting up subscriptions&lt;/strong&gt;: Connecting to a WebSocket or listening to a real-time service.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Manual DOM manipulation&lt;/strong&gt;: Directly changing the DOM, like focusing an input field or integrating with a non-React library.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Logging&lt;/strong&gt;: Sending analytics or error reports to a logging service.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Using browser APIs&lt;/strong&gt;: Interacting with &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;Cookies&lt;/code&gt;, &lt;code&gt;document.title&lt;/code&gt;, or timers like &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;setInterval&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  It Runs &lt;em&gt;After&lt;/em&gt; the Paint
&lt;/h3&gt;

&lt;p&gt;A critical detail that often trips up developers is &lt;em&gt;when&lt;/em&gt; &lt;code&gt;useEffect&lt;/code&gt; runs. Unlike &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;componentDidUpdate&lt;/code&gt;, which could block the browser from painting, &lt;code&gt;useEffect&lt;/code&gt; is deferred. It runs &lt;em&gt;after&lt;/em&gt; React has rendered your component and the browser has painted the result to the screen.&lt;/p&gt;

&lt;p&gt;This is a huge performance benefit. It ensures that side effects, which can be slow, don't make your UI feel sluggish. The user sees the updated UI first, and then the effect runs in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception: It’s Not for All Logic
&lt;/h3&gt;

&lt;p&gt;Because &lt;code&gt;useEffect&lt;/code&gt; is so versatile, it's tempting to put any and all logic inside it. This is a common anti-pattern. &lt;code&gt;useEffect&lt;/code&gt; is for synchronizing with external systems. If you can calculate a value or derive state directly during the render, you don't need an effect. Using it for simple computations adds unnecessary complexity and can lead to bugs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rule of Thumb:&lt;/strong&gt; If your logic doesn't interact with the outside world, it probably doesn't belong in &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. The Dependencies Array Demystified
&lt;/h2&gt;

&lt;p&gt;The second argument to &lt;code&gt;useEffect&lt;/code&gt; is the dependencies array. This array is the key to controlling &lt;em&gt;when&lt;/em&gt; your effect runs. Get it right, and your components will be efficient and predictable. Get it wrong, and you'll face bugs like infinite loops and stale data.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Modes of &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can think of the dependency array as having three primary modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Dependency Array:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... })&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: After the initial render and &lt;em&gt;every single re-render&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why it's often bad&lt;/strong&gt;: This can be inefficient and dangerous. If the effect triggers a state update, it will cause a re-render, which will trigger the effect again, leading to an infinite loop. Use this mode with extreme caution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Empty Array:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... }, [])&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: Only once, after the initial render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;This is the equivalent of &lt;code&gt;componentDidMount&lt;/code&gt;&lt;/strong&gt;. It’s perfect for one-time setup logic, like fetching initial data or setting up a subscription that doesn't depend on any props or state.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Array with Dependencies:&lt;/strong&gt; &lt;code&gt;useEffect(() =&amp;gt; { ... }, [prop1, stateValue])&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;When it runs&lt;/strong&gt;: After the initial render and any time a value in the dependency array changes.&lt;/li&gt;
&lt;li&gt;  This is the most common and powerful mode. It lets you synchronize your component with a specific piece of data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How React Compares Dependencies
&lt;/h3&gt;

&lt;p&gt;React performs a &lt;strong&gt;shallow comparison&lt;/strong&gt; of the items in the dependency array. It checks if &lt;code&gt;oldValue === newValue&lt;/code&gt; for each dependency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For &lt;strong&gt;primitive values&lt;/strong&gt; (strings, numbers, booleans), this works as you'd expect. &lt;code&gt;5 === 5&lt;/code&gt; is true, but &lt;code&gt;5 === 6&lt;/code&gt; is false.&lt;/li&gt;
&lt;li&gt;  For &lt;strong&gt;reference values&lt;/strong&gt; (objects, arrays, functions), it checks if the reference itself has changed, not the contents. A new object or array is created on every render, so &lt;code&gt;{} !== {}&lt;/code&gt;. This is a classic source of infinite loops.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ⚠️ Anti-pattern: This will cause an infinite loop!&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOptions&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="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;// Some logic&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// `options` is a new object on every render&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Fix Shallow Comparison Issues
&lt;/h3&gt;

&lt;p&gt;So, how do you depend on an object or array without causing an infinite loop? Here are the recommended solutions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Memoize the Dependency with &lt;code&gt;useMemo&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need to depend on an object or array that is calculated during render, wrap it in &lt;code&gt;useMemo&lt;/code&gt;. This ensures that the object's reference only changes when its own underlying dependencies change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Memoize the object&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;filterSettings&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// `options` will only be a new object when `filterSettings` changes&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&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;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterSettings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;includeDrafts&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="nx"&gt;filterSettings&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="c1"&gt;// This effect now only runs when `options` actually changes&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;options&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;2. Depend on Primitive Values&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simplest solution is often the best. If your effect only needs a few properties from an object, depend on those properties directly. Primitives are compared by value, so this is always safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Depend on the primitive value&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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="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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User ID is: &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="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="c1"&gt;// Depend on `user.id`, not the whole `user` object&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;3. Other Advanced Solutions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;JSON.stringify&lt;/code&gt;&lt;/strong&gt;: As a quick fix, you can serialize the object into a string: &lt;code&gt;[JSON.stringify(options)]&lt;/code&gt;. This works but can be inefficient for large objects and may not handle all edge cases (like key order).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deep Comparison Hooks&lt;/strong&gt;: You can find or create a custom hook (e.g., &lt;code&gt;useDeepCompareEffect&lt;/code&gt;) that uses a utility like &lt;code&gt;lodash.isEqual&lt;/code&gt; to perform a deep comparison instead of a shallow one. This is a powerful but often unnecessary abstraction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tips to Avoid Common Pitfalls
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Stale Closures&lt;/strong&gt;: If you use a state variable or prop inside an effect but forget to include it in the dependency array, the effect will “close over” the initial value of that variable. It will never see the updated value, leading to bugs. The &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt; package is essential for catching this.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Infinite Loops&lt;/strong&gt;: Always be careful with objects, arrays, and functions in the dependency array. If you must use them, ensure they are stable between renders. Use &lt;code&gt;useCallback&lt;/code&gt; for functions and &lt;code&gt;useMemo&lt;/code&gt; for objects/arrays to memoize them.
&amp;gt; &lt;strong&gt;Pro Tip:&lt;/strong&gt; If your effect doesn't use any props or state, give it an empty dependency array &lt;code&gt;[]&lt;/code&gt;. If it does, include every one of them in the array. Let the linter guide you.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Cleanup Functions and the “Return” Mystery
&lt;/h2&gt;

&lt;p&gt;Many side effects need to be undone. If you set up a subscription, you need to unsubscribe. If you start a timer, you need to clear it. This is where the &lt;code&gt;useEffect&lt;/code&gt; cleanup function comes in. It’s the &lt;code&gt;componentWillUnmount&lt;/code&gt; of the Hooks world, but much more powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;useEffect&lt;/code&gt; Can Return a Function
&lt;/h3&gt;

&lt;p&gt;If you return a function from your &lt;code&gt;useEffect&lt;/code&gt; callback, React will store it and run it at the appropriate time. This design is brilliant because it keeps the logic for setting up and tearing down an effect right next to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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;// The effect logic: runs after every render where dependencies change&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;Timer fired!&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="c1"&gt;// The cleanup function: returned by the effect&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;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;Clearing timer...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerId&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;// Empty array means this effect runs once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When Does the Cleanup Function Run?
&lt;/h3&gt;

&lt;p&gt;This is a key point of confusion. The cleanup function runs in two scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Before the effect runs again&lt;/strong&gt;: If your dependencies change and the effect is about to re-run, React first runs the cleanup function from the &lt;em&gt;previous&lt;/em&gt; render. This ensures you don't have multiple subscriptions or timers running at once.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;On unmount&lt;/strong&gt;: When the component is removed from the DOM, React runs the cleanup function from the &lt;em&gt;last&lt;/em&gt; render.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This behavior ensures that your effects are always cleaned up, preventing what are sometimes called “zombie effects”—lingering side effects from a component that is no longer on the screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Cases for Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Clearing timeouts or intervals&lt;/strong&gt;: As shown above, &lt;code&gt;clearTimeout&lt;/code&gt; and &lt;code&gt;clearInterval&lt;/code&gt; are essential to prevent timers from firing after a component has unmounted.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unsubscribing from events or sockets&lt;/strong&gt;: If you use &lt;code&gt;addEventListener&lt;/code&gt; or connect to a WebSocket, you must remove the listener or close the connection to avoid memory leaks and unnecessary processing.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Canceling pending requests&lt;/strong&gt;: For data fetching, you can use an &lt;code&gt;AbortController&lt;/code&gt; to cancel a network request if the component unmounts or the dependencies change before the request completes. This prevents you from trying to update the state of an unmounted component.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Why Cleanup Prevents Memory Leaks
&lt;/h3&gt;

&lt;p&gt;Without cleanup, your application would slowly degrade. Event listeners would pile up, subscriptions would remain active, and timers would fire unexpectedly, all consuming memory and CPU cycles for components that no longer exist. The &lt;code&gt;useEffect&lt;/code&gt; cleanup function provides a simple, reliable pattern to keep your application healthy and performant.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Multiple &lt;code&gt;useEffect&lt;/code&gt;s: Execution and Cleanup Order
&lt;/h2&gt;

&lt;p&gt;A single component can have multiple &lt;code&gt;useEffect&lt;/code&gt; hooks. This is a powerful feature for separating unrelated logic. But when you have more than one, it's important to understand the order in which they run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution Order: Top to Bottom
&lt;/h3&gt;

&lt;p&gt;React executes &lt;code&gt;useEffect&lt;/code&gt; hooks in the same order they are declared in your component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&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;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;First effect runs&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="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;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;Second effect runs&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Console output on mount:&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect runs"&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect runs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This predictable, top-to-bottom order allows you to orchestrate side effects that might depend on each other, although it's generally better to keep them independent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup Order: Bottom to Top (Reverse Order)
&lt;/h3&gt;

&lt;p&gt;Here's the interesting part: the cleanup functions run in the &lt;strong&gt;reverse order&lt;/strong&gt; of the effects. When the component unmounts (or before a re-run), React will clean up the second effect, then the first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&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;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;First effect setup&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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First effect cleanup&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="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;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;Second effect setup&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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second effect cleanup&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// On mount:&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect setup"&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect setup"&lt;/span&gt;

&lt;span class="c1"&gt;// On unmount:&lt;/span&gt;
&lt;span class="c1"&gt;// "Second effect cleanup"&lt;/span&gt;
&lt;span class="c1"&gt;// "First effect cleanup"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like a stack: the last effect that was set up is the first one to be torn down. This LIFO (Last-In, First-Out) order ensures that dependencies are cleaned up correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Splitting Concerns is Cleaner
&lt;/h3&gt;

&lt;p&gt;The ability to use multiple &lt;code&gt;useEffect&lt;/code&gt; hooks is the primary reason Hooks are so good at promoting separation of concerns. Instead of a monolithic &lt;code&gt;componentDidMount&lt;/code&gt; that does everything, you can have a dedicated effect for each piece of side-effect logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Separating Data Fetching from UI Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you need to fetch data and also update the document title based on that data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;postId&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;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPost&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;// Effect 1: Handles data fetching&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/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;postId&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;setPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;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="c1"&gt;// Cleanup for this effect&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Effect 2: Handles updating the document title&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;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&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="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;post&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Runs only when the `post` state changes&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;post&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;post&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is incredibly clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first effect is solely responsible for fetching data. Its dependency is &lt;code&gt;postId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second effect is solely responsible for a UI side effect (updating the title). Its dependency is &lt;code&gt;post&lt;/code&gt;.
The two pieces of logic are completely decoupled.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Debugging &lt;code&gt;useEffect&lt;/code&gt; Like a Pro
&lt;/h2&gt;

&lt;p&gt;Even with a solid understanding, &lt;code&gt;useEffect&lt;/code&gt; can still be a source of bugs. Knowing how to debug it effectively is a superpower. Here are common issues and how to solve them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Pitfalls and How to Spot Them
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Infinite Loops&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: Your app becomes unresponsive, the fan kicks on, and the browser might crash.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: An effect is updating state, which causes a re-render, which triggers the effect again. This usually happens when a dependency is an object, array, or function that is re-created on every render.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Memoize reference-type dependencies with &lt;code&gt;useMemo&lt;/code&gt; or &lt;code&gt;useCallback&lt;/code&gt;. For state updates, use the functional update form (&lt;code&gt;setState(prev =&amp;gt; ...)&lt;/code&gt;), which can sometimes remove the need to depend on the state itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Missing Dependencies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: The effect doesn't re-run when you expect it to. Data becomes stale.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: You used a prop or state variable inside the effect but didn't add it to the dependency array. The effect has a "stale closure" over the old value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Turn on the &lt;code&gt;react-hooks/exhaustive-deps&lt;/code&gt; ESLint rule. It's your best friend for catching this. Trust the linter; it's almost always right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stale State in Async Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Symptom&lt;/strong&gt;: An async function (like a &lt;code&gt;setTimeout&lt;/code&gt; callback) reads a state variable, but it sees an old value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cause&lt;/strong&gt;: The closure was created when the effect ran, capturing the state at that moment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fix&lt;/strong&gt;: Use &lt;code&gt;useRef&lt;/code&gt; to store a mutable value that can be read at any time without re-triggering the effect. Or, refactor to include the state in the dependency array and properly clean up the effect.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Use the ESLint Rule (and When to Ignore It)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;react-hooks/exhaustive-deps&lt;/code&gt; ESLint rule is a lifesaver. It statically analyzes your &lt;code&gt;useEffect&lt;/code&gt; calls and warns you about missing dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;99% of the time, you should follow its advice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When is it okay to ignore it? Very rarely. One legitimate case is when you &lt;em&gt;intentionally&lt;/em&gt; want to capture the initial value of a prop and never react to its changes. Even then, it's often cleaner to store that value in a &lt;code&gt;useRef&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// To ignore, add this comment. But think twice!&lt;/span&gt;
&lt;span class="c1"&gt;// eslint-disable-next-line react-hooks/exhaustive-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tracing with Logs and Custom Hooks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simple Logging&lt;/strong&gt;: The easiest way to see when an effect runs and cleans up.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Effect ran with value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myValue&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cleanup for value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myValue&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;myValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom &lt;code&gt;useTraceUpdate&lt;/code&gt; Hook&lt;/strong&gt;: Create a custom hook to see exactly which prop caused an effect to re-run.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&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;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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTraceUpdate&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prev&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="nx"&gt;props&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;changedProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&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="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="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;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&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="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ps&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changedProps&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Changed props:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;changedProps&lt;/span&gt;&lt;span class="p"&gt;);&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="nx"&gt;current&lt;/span&gt; &lt;span class="o"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  React DevTools Profiler
&lt;/h3&gt;

&lt;p&gt;The React DevTools are indispensable. Use the Profiler to record a user interaction and see exactly why your components re-rendered. The "Why did this render?" checkbox in the component inspector is a great starting point. For effects, the Profiler's flamegraph can help you spot long-running effects that might be slowing down your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6kg3wjbjn8diklxmun7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6kg3wjbjn8diklxmun7.gif" alt=" " width="800" height="310"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image Ref: &lt;a href="https://legacy.reactjs.org" rel="noopener noreferrer"&gt;https://legacy.reactjs.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Tips: &lt;code&gt;useRef&lt;/code&gt; for Tracking
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to access the previous value of a prop or state inside an effect. &lt;code&gt;useRef&lt;/code&gt; is perfect for this. Since updating a ref doesn't trigger a re-render, you can use it to store values across renders without affecting the component's lifecycle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCountRef&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="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;prevCountRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Store the current count for the next render&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// No dependency array, so this runs on every render&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevCountRef&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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Now&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;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;prevCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. When Not to Use &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The most powerful lesson is often learning what a tool is &lt;em&gt;not&lt;/em&gt; for. Overusing &lt;code&gt;useEffect&lt;/code&gt; can lead to complex, inefficient, and buggy components. The golden rule is: &lt;strong&gt;if it can be done during render, don’t put it in &lt;code&gt;useEffect&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern: Unnecessary State Mirroring
&lt;/h3&gt;

&lt;p&gt;A common mistake is to use &lt;code&gt;useEffect&lt;/code&gt; to update a state variable in response to a prop change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&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;user&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;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;setName&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;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Mirrors the prop in state&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is redundant. You already have &lt;code&gt;user.name&lt;/code&gt; from props. The effect adds an unnecessary re-render and makes the data flow confusing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Derive state directly from props&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&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="c1"&gt;// No need for an effect or separate state&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;user&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Anti-Pattern: Computations and Derived State
&lt;/h3&gt;

&lt;p&gt;Don't use effects for calculations that can be done directly during rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&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;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTotal&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;newTotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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;setTotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTotal&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;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is overly complex. The total can be calculated on every render. If the calculation is expensive, use &lt;code&gt;useMemo&lt;/code&gt; to memoize it, but still don't use &lt;code&gt;useEffect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct: Calculate during render&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct (for expensive calculations)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&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;total&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;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prefer Event Handlers for User Actions
&lt;/h3&gt;

&lt;p&gt;Side effects should be caused by a render, not a user event. If a user action (like clicking a button) needs to trigger a state change, do it directly in the event handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Anti-pattern&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyForm&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;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="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;submittedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSubmittedValue&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="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;submittedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// send to API&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;submittedValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSubmittedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is indirect. The state change is just a trigger for the effect. The logic belongs in the event handler itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correct&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyForm&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;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="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;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// send to API directly&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&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;Submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By avoiding these anti-patterns, you keep your components simpler, more predictable, and more performant.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Practical Examples &amp;amp; Patterns
&lt;/h2&gt;

&lt;p&gt;Theory is great, but code is better. Let's look at some common, production-ready patterns for &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern: Data Fetching with &lt;code&gt;AbortController&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the canonical example of a robust data fetching effect. It handles loading and error states, and it cancels the request if the component unmounts or the &lt;code&gt;userId&lt;/code&gt; changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&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="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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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="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="kd"&gt;const&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="o"&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;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="s2"&gt;`https://api.example.com/users/&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="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="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="s1"&gt;Failed to fetch&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;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="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="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;finally&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;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="c1"&gt;// Cleanup function to abort the request&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;userId&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;user&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern: Syncing the Browser Tab Title
&lt;/h3&gt;

&lt;p&gt;A simple but effective use case. This effect synchronizes an external part of the browser (the tab title) with the component's state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDocumentTitle&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="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="c1"&gt;// Store the original title so we can restore it on unmount&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&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;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;originalTitle&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;title&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 a component&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useDocumentTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Page&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern: Custom Hooks Abstraction (e.g., &lt;code&gt;useLocalStorage&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;If you find yourself writing the same &lt;code&gt;useEffect&lt;/code&gt; logic repeatedly, it's time to extract it into a custom hook. This is one of the most powerful features of Hooks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&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;storedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStoredValue&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="o"&gt;=&amp;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&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;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&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;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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;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;error&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;initialValue&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;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;try&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;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="nx"&gt;key&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="nx"&gt;storedValue&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;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;error&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;storedValue&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;storedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStoredValue&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 a component&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Settings&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;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="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;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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Light&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="nx"&gt;value&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Dark&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&amp;gt;    &amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;select&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Wrap-Up
&lt;/h2&gt;

&lt;p&gt;Mastering &lt;code&gt;useEffect&lt;/code&gt; is a journey from understanding its rules to developing an intuition for its purpose. It’s not just a replacement for lifecycle methods; it’s a fundamentally different way of thinking about synchronizing your component with the world outside React.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;useEffect&lt;/code&gt; Cheat Sheet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Use it for&lt;/strong&gt;: Side effects (data fetching, subscriptions, manual DOM changes).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How to control it&lt;/strong&gt;: The dependency array is key.

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;[]&lt;/code&gt;: Runs once on mount.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;[dep]&lt;/code&gt;: Runs when &lt;code&gt;dep&lt;/code&gt; changes.&lt;/li&gt;
&lt;li&gt;  No array: Runs on every render (use with caution!).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;How to clean up&lt;/strong&gt;: Return a function from the effect. It runs before the next effect or on unmount.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;When to avoid it&lt;/strong&gt;: For derived state or simple computations. If you can calculate it during render, do it.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visual Summary
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  The Future of Effects
&lt;/h3&gt;

&lt;p&gt;The React team is always exploring ways to make effects even better. While nothing is set in stone, future versions of React might introduce new APIs or refine the behavior of &lt;code&gt;useEffect&lt;/code&gt; to make it even more intuitive and less error-prone. Staying engaged with the React community will keep you prepared for what's next.&lt;/p&gt;

&lt;p&gt;By following these principles, you can write cleaner, more efficient, and more predictable React components. Happy coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me on Medium, Dev.to, and LinkedIn! 🚀😊
&lt;/h2&gt;

&lt;p&gt;Your support and engagement mean the world to me.&lt;br&gt;&lt;br&gt;
Let's create a community of knowledge enthusiasts and professionals striving for excellence and continuous learning.  &lt;/p&gt;

&lt;p&gt;Click the links below to follow me on all platforms:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/mrajaeim" rel="noopener noreferrer"&gt;Connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📝 &lt;strong&gt;&lt;a href="https://medium.com/@mrajaeim" rel="noopener noreferrer"&gt;Follow on Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
💻 &lt;strong&gt;&lt;a href="https://dev.to/mrajaeim"&gt;Follow on Dev.to&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;




&lt;p&gt;I’m committed to providing the most up-to-date and relevant information.&lt;br&gt;&lt;br&gt;
As things evolve or new insights emerge, I may revisit and update this article to ensure it remains a valuable resource.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
