<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Peter Ogbonna</title>
    <description>The latest articles on DEV Community by Peter Ogbonna (@peterintech).</description>
    <link>https://dev.to/peterintech</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%2F859035%2F1b02f72b-8261-45be-bf32-722c45b62255.png</url>
      <title>DEV Community: Peter Ogbonna</title>
      <link>https://dev.to/peterintech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peterintech"/>
    <language>en</language>
    <item>
      <title>Understanding Next.js Cache (Part 5)</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Sat, 28 Mar 2026 12:24:28 +0000</pubDate>
      <link>https://dev.to/peterintech/understanding-nextjs-cache-part-5-3lok</link>
      <guid>https://dev.to/peterintech/understanding-nextjs-cache-part-5-3lok</guid>
      <description>&lt;p&gt;If you have built an application using the Next.js App Router, there is a 100% chance you've come across the issue of updating the database but the page still showing the old data.&lt;/p&gt;

&lt;p&gt;Welcome to the &lt;em&gt;Server-Side Caching&lt;/em&gt; paradigm. &lt;/p&gt;

&lt;p&gt;In the React SPA world, if a user hits refresh, the cache is wiped clean. Next.js flipped the script. It caches data on the &lt;em&gt;Server&lt;/em&gt;, and by default, it caches everything, aggressively. &lt;/p&gt;

&lt;p&gt;To understand why your app is behaving the way it is we'll look at some concepts to understand how the Next.js cache actually works:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Bakery Analogy (API Data vs Pages)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Think of your Next.js application as a Bakery. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The API Data (The Data Cache)&lt;/em&gt; will be our raw ingredients (flour, sugar, eggs) fetched from your database or external APIs. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The Pages (The Full Route Cache)&lt;/em&gt; will be the fully baked cake sitting in the display window.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next.js doesn't just cache the finished HTML (cake), it also caches the raw JSON (ingredients). This means if 50 users from different location visit your site at the exact same time, Next.js doesn't overwhelm your database with 50 queries. It uses the cached ingredients to serve everyone instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The 4 Layers of Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The most common point of confusion is what happens when a user hits the refresh button. Let's break down the four layers of the Next.js cache using our kitchen&lt;br&gt;
This now leads us to the 4 layers of caching when dealing with Next.js:&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;1. Request Memoization (The Countertop/Clipboard)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If three different React components on the same page all call &lt;code&gt;fetch('/api/user')&lt;/code&gt;, Next.js deduplicates them. It only makes the network request once and shares the result. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The countertop/clipboard is wiped clean after every single page render.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;2. Router Cache (The Customer's Plate)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As a user clicks around your app, Next.js stores the React Server Component payloads in the browser's memory. This makes clicking the &lt;em&gt;Back&lt;/em&gt; button feel instantaneous.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This doesn't survive a refresh either, a hard refresh wipes the browser's memory (washes the plate). &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;3. Data Cache (The Pantry)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is where Next.js stores the raw JSON data returned from your database across &lt;em&gt;multiple&lt;/em&gt; user sessions. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This survives a refresh, if you refresh the page, the browser asks the server for new data, but the server just pulls the same cached data from the pantry. &lt;br&gt;
This is why refreshing often doesn't "fix" stale data!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;4. Full Route Cache (The Display Window)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Next.js takes the cached data and your components, rendering them into pure, static HTML at build time. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This survives a refresh as it serves the pre-rendered HTML file until the underlying &lt;em&gt;data cache&lt;/em&gt; is explicitly invalidated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Taking Control of the Cache&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Caching is fantastic for performance, but dynamic apps need dynamic data. Here is how you take control and tell Next.js to throw away the old ingredients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Opting Out Entirely (No Caching)&lt;/strong&gt;&lt;br&gt;
If a piece of data changes constantly (like a live stock ticker or bank account balance), tell Next.js not to cache the &lt;code&gt;fetch&lt;/code&gt; request at all:&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;// Fetched fresh on every single request&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Time-Based Revalidation (Stale-While-Revalidate)&lt;/strong&gt;&lt;br&gt;
Tell Next.js to keep the cache for a specific amount of time before fetching fresh data in the background:&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;// Revalidate this data every 3600 seconds (1 hour)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&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;3. On-Demand Revalidation (The "Invalidate" Button)&lt;/strong&gt;&lt;br&gt;
When a user submits a form (like updating their profile), you need to instantly clear the cache for that specific page. You do this inside a Server Action:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&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;revalidatePath&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;next/cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Tell Next.js to throw away the cached HTML and data for this route&lt;/span&gt;
  &lt;span class="nf"&gt;revalidatePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&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;h3&gt;
  
  
  &lt;strong&gt;The Grand Finale&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Over these 5 articles, we went from understanding the theory of "Fresh vs Stale" to mastering HTTP headers, taming React-Query/Redux client state and finally conquering the Next.js server cache. &lt;/p&gt;

&lt;p&gt;Caching is no longer just a backend optimization. It is the beating heart of the frontend User Experience. Master it, and you will build applications that are absolutely instantaneous and save server cost &lt;/p&gt;

&lt;p&gt;Now go build something fast.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Automated Caching with RTK Query (Part 4)</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Sat, 28 Feb 2026 14:10:23 +0000</pubDate>
      <link>https://dev.to/peterintech/automated-caching-with-rtk-query-part-4-4c5n</link>
      <guid>https://dev.to/peterintech/automated-caching-with-rtk-query-part-4-4c5n</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/peterintech/tanstack-query-changed-everything-part-3-5e6l"&gt;Part 3&lt;/a&gt;, we looked at how Tanstack Query revolutionized caching by moving server state out of our global state managers. But what if you work on a massive enterprise application that is already deeply invested in &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Do you have to rip out Redux to get good caching? Absolutely not.&lt;/p&gt;

&lt;p&gt;Welcome to &lt;em&gt;Part 4&lt;/em&gt;. Let's talk about the tool that made Redux fun again: &lt;strong&gt;RTK Query&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;If you spend enough time on tech Twitter (X), you will inevitably hear people saying things like &lt;em&gt;"Redux is dead."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is not true as redux is powering some of the largest, most complex applications on the internet. However, the way we write Redux has fundamentally changed with the introduction of &lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux-Toolkit&lt;/a&gt; (RTK)&lt;/p&gt;

&lt;p&gt;In the old days, fetching a list of users in Redux required a mountain of boilerplate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write an &lt;code&gt;Action&lt;/code&gt; for &lt;code&gt;FETCH_USERS_REQUEST&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write an &lt;code&gt;Action&lt;/code&gt; for &lt;code&gt;FETCH_USERS_SUCCESS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write an &lt;code&gt;Action&lt;/code&gt; for &lt;code&gt;FETCH_USERS_FAILURE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write a massive &lt;code&gt;Thunk&lt;/code&gt; to make the actual API call.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;Reducer&lt;/code&gt; to handle the &lt;code&gt;isLoading&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt; states.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It was exhausting. And worst of all? It didn't even cache the data properly. If you navigated away and came back, your &lt;code&gt;Thunk&lt;/code&gt; would just fetch it all over again.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;Part 4&lt;/em&gt; of our series, we are looking at &lt;strong&gt;RTK Query&lt;/strong&gt; (Redux Toolkit Query) which was primarily built for data fetching and caching solution integrated directly into Redux.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Architecture: Centralized vs. Decentralized&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/peterintech/tanstack-query-changed-everything-part-3-5e6l"&gt;Part 3&lt;/a&gt;, we looked at React Query. React Query is largely decentralized. You call &lt;code&gt;useQuery&lt;/code&gt; wherever you need it, and it magically syncs up based on a &lt;code&gt;queryKey&lt;/code&gt; (like &lt;code&gt;['users']&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;RTK Query takes a different, highly structured approach. It uses the &lt;em&gt;API Slice&lt;/em&gt; pattern.&lt;/p&gt;

&lt;p&gt;Instead of writing fetch calls scattered across your components, you define your entire API in one central location.&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;createApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchBaseQuery&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;@reduxjs/toolkit/query/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducerPath&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fetchBaseQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseUrl&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/users/&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&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="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;// RTK Query auto-generates custom React hooks for you&lt;/span&gt;
&lt;span class="k"&gt;export&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;useGetUsersQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useUpdateUserMutation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apiSlice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With just that block of code, RTK Query replaces hundreds of lines of legacy Redux boilerplate. It automatically handles the fetching, the &lt;code&gt;isLoading&lt;/code&gt; state, the deduplication, and the caching.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Solving the Hardest Problem using "Tags"&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/peterintech/the-frontend-caching-handbook-part-1-2g30"&gt;Part 1&lt;/a&gt;, we established that cache invalidation (knowing when to throw old data away) is one of the hardest problems in computer science.&lt;/p&gt;

&lt;p&gt;RTK Query solves this using an incredibly elegant system called &lt;em&gt;Automated Tag-based Invalidation&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Think of a Tag like a sticky note you put on a piece of data.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;providesTags&lt;/code&gt; (Applying the label):&lt;br&gt;
When you fetch the list of users, you tell RTK Query to tag that cached data with &lt;code&gt;['User']&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;invalidatesTags&lt;/code&gt; (Tearing off the label): &lt;br&gt;
When you run a mutation to update a specific user, you tell RTK Query to invalidate the &lt;code&gt;['User']&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside your endpoints builder:&lt;/span&gt;
&lt;span class="nx"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;providesTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Label this data as 'User'&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="nx"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/users/&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;invalidatesTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Throw away any cache labeled 'User'&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The moment &lt;code&gt;updateUser&lt;/code&gt; succeeds, RTK Query automatically sees that the &lt;code&gt;['User']&lt;/code&gt; tag was invalidated. It instantly looks at your app, finds any component currently displaying the &lt;code&gt;getUsers&lt;/code&gt; query, and forces a background refetch.&lt;/p&gt;

&lt;p&gt;Your UI updates automatically. No manual dispatching. No messy states.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;React Query vs. RTK Query: Which should you choose?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since both tools solve the same problem (Server State caching), which one should you use?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose React Query:&lt;/strong&gt; If you are starting a new project, you don't need a massive global client-state store, or you prefer a lightweight, flexible, decentralized approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose RTK Query:&lt;/strong&gt; If you are already using Redux Toolkit. Adding React Query to an existing Redux app means you now have two separate stores to manage and debug. RTK Query drops right into your existing &lt;code&gt;Redux DevTools&lt;/code&gt;, keeping your architecture clean and unified.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What’s Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Up to this point, we have focused entirely on caching data inside the user's browser (Client-Side Caching). But the frontend world is shifting.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 5&lt;/strong&gt;, the grand finale of this series, we are crossing the chasm into &lt;strong&gt;Server-Side Caching&lt;/strong&gt;. We will look at Next.js (using App Router) and how it aggressively caches not just data, but entire HTML pages and React Server Components.&lt;/p&gt;

&lt;p&gt;Prepare to have your mental model challenged one last time. See you in Part 5.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>redux</category>
      <category>react</category>
    </item>
    <item>
      <title>TanStack Query Changed Everything (Part 3)</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Wed, 18 Feb 2026 12:00:30 +0000</pubDate>
      <link>https://dev.to/peterintech/tanstack-query-changed-everything-part-3-5e6l</link>
      <guid>https://dev.to/peterintech/tanstack-query-changed-everything-part-3-5e6l</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/peterintech/the-invisible-layer-mastering-http-caching-part-2-31gn"&gt;Part 2&lt;/a&gt;, we learnt about the invisible layer of HTTP caching. Now, we move to the application layer.&lt;/p&gt;

&lt;p&gt;You can relate to the nightmare associated with managing data coming from the server.&lt;/p&gt;

&lt;p&gt;We have all written this code before:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;useState&lt;/code&gt; for &lt;code&gt;data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;useState&lt;/code&gt; for &lt;code&gt;isLoading&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;useState&lt;/code&gt; for &lt;code&gt;error&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;useEffect&lt;/code&gt; to fetch the data.&lt;/li&gt;
&lt;li&gt;Realize we forgot to handle race conditions like what if the component unmounts before the fetch finishes?&lt;/li&gt;
&lt;li&gt;Realize we have no way to &lt;a href="https://www.oracle.com/data-deduplication" rel="noopener noreferrer"&gt;deduplicate&lt;/a&gt; requests if two components need the same data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As I argued in my &lt;a href="https://dev.to/peterintech/stop-writing-messy-states-why-i-swapped-useeffect-for-react-router-loaders-46mm"&gt;previous article about React Router Loaders&lt;/a&gt;, manual state management looks messy and at times, tend to be where bugs go to hide.&lt;/p&gt;

&lt;p&gt;Today, we look at &lt;em&gt;&lt;a href="https://tanstack.com/query/v4/docs/framework/react/overview" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt; (React Query)&lt;/em&gt;*. It isn't just a data fetching library; it is an async state manager that brings the &lt;code&gt;stale-while-revalidate&lt;/code&gt; strategy (discussed in &lt;a href="https://dev.to/peterintech/the-invisible-layer-mastering-http-caching-part-2-31gn"&gt;part 2&lt;/a&gt;) directly into your components.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Philosophy: Server State vs. Client State
&lt;/h3&gt;

&lt;p&gt;The biggest breakthrough TanStack Query brought to the frontend world is the realization that &lt;em&gt;Server State is not the same as Client State.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Client State&lt;/em&gt; asks these questions: Is the modal open? What is the current theme? Is the sidebar collapsed? All these belongs in &lt;code&gt;useState&lt;/code&gt;, &lt;a href="https://react.dev/reference/react/useContext" rel="noopener noreferrer"&gt;Context&lt;/a&gt;, or &lt;a href="https://zustand.docs.pmnd.rs/getting-started/introduction" rel="noopener noreferrer"&gt;Zustand&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;em&gt;Server State&lt;/em&gt;, we talk about: The list of users, the current blog post.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Server state is "borrowed" as it's data that exists remotely, owned by the server (somebody else), hence can become &lt;code&gt;stale&lt;/code&gt; without you knowing. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;TanStack Query&lt;/em&gt; is designed explicitly to manage &lt;code&gt;server state&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Side-by-Side Comparison
&lt;/h3&gt;

&lt;p&gt;Let's look at the difference.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Old Way&lt;/em&gt; - using &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="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="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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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;let&lt;/span&gt; &lt;span class="nx"&gt;isMounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;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="nf"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isMounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&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="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;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="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;/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;&lt;em&gt;The New way&lt;/em&gt; - using &lt;code&gt;TanStack Query&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;// UserProfile.jsx&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;useQuery&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;@tanstack/react-query&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;UserProfile&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="na"&gt;data&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&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="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;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="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;/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;It looks similar, but under the hood, TanStack Query is doing something magical, which is &lt;em&gt;Global Caching&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you use this &lt;code&gt;&amp;lt;UserProfile /&amp;gt;&lt;/code&gt; component in 5 different places on your screen, React Query will deduplicate the requests. It will only fetch once and serve the result to all 5 components instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Configuration: &lt;code&gt;staleTime&lt;/code&gt; vs &lt;code&gt;gcTime&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;TanStack Query uses the combo of these two to handle caching&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;code&gt;staleTime&lt;/code&gt; (The "Freshness" Timer)
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This controls &lt;strong&gt;when data is considered old&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Default is &lt;code&gt;0&lt;/code&gt; (Zero).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If &lt;code&gt;staleTime&lt;/code&gt; is &lt;code&gt;5000&lt;/code&gt; (5 seconds), the data remains &lt;em&gt;Fresh&lt;/em&gt; for 5 seconds. During this time, if another component asks for this data, it uses the cache preventing a background refetch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After 5 seconds, the data becomes &lt;em&gt;Stale&lt;/em&gt;, TanStack Query will still serve it instantly but will trigger a background refetch to update it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It's default is zero, because TanStack Query assumes your data is always out of date.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. &lt;code&gt;gcTime&lt;/code&gt; (The "Garbage Collection" Timer)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Formerly known as &lt;code&gt;cacheTime&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This controls &lt;strong&gt;how long unused data stays in memory&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Default is &lt;code&gt;300000&lt;/code&gt; (5 minutes).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you navigate away from the &lt;code&gt;UserProfile&lt;/code&gt; page, the data is no longer being used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React Query keeps it in memory for 5 minutes in case you come back.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you return within 5 minutes, the data appears instantly else, the data is gone and you get a refetch.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solving the Hardest Problem (Invalidation)
&lt;/h3&gt;

&lt;p&gt;In &lt;a href="https://dev.to/peterintech/the-frontend-caching-handbook-part-1-2g30"&gt;Part 1&lt;/a&gt;, we said invalidation is the hardest problem in CS. &lt;/p&gt;

&lt;p&gt;TanStack Query solves this with &lt;code&gt;invalidateQueries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you have a mutation to update a user's name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;mutationFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onSuccess&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="c1"&gt;// This tells TanStack Query the 'user' data is now dirty. It uses the 'queryKey' to identify which to invalidate&lt;/span&gt;
    &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When this runs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The mutation succeeds.&lt;/li&gt;
&lt;li&gt;React Query marks the &lt;code&gt;['user']&lt;/code&gt; cache as &lt;em&gt;Stale&lt;/em&gt; immediately.&lt;/li&gt;
&lt;li&gt;Any component currently displaying the user triggers a background refetch, hence automatically updating the UI!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;TanStack Query is the standard for general Frontend applications. But what if you are using Redux? What if you want this caching power but integrated tightly with your global store?&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;Part 4&lt;/em&gt;, we will explore &lt;a href="https://redux-toolkit.js.org/tutorials/rtk-query" rel="noopener noreferrer"&gt;RTK Query&lt;/a&gt; (Redux Toolkit Query). We will see how it takes these same concepts and applies them to the Redux ecosystem.&lt;/p&gt;

&lt;p&gt;See you in Part 4.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>The Invisible Layer: Mastering HTTP Caching (Part 2)</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Mon, 16 Feb 2026 22:45:36 +0000</pubDate>
      <link>https://dev.to/peterintech/the-invisible-layer-mastering-http-caching-part-2-31gn</link>
      <guid>https://dev.to/peterintech/the-invisible-layer-mastering-http-caching-part-2-31gn</guid>
      <description>&lt;p&gt;"I updated the data in the database, but the user is still seeing the old version!"&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%2Fvaitme96wljobfph9hzt.jpg" 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%2Fvaitme96wljobfph9hzt.jpg" alt="Confused dude" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever screamed this while frantically hard-refreshing your browser, you have met the &lt;em&gt;HTTP Cache&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href="https://dev.to/peterintech/the-frontend-caching-handbook-part-1-2g30"&gt;Part 1&lt;/a&gt;&lt;/strong&gt;, I discussed the mindset of caching. Today, we look at the mechanics.&lt;/p&gt;

&lt;p&gt;Most frontend engineers don't realize the massive conversation happening in the Network Tab. Conversations in the &lt;em&gt;Response Headers&lt;/em&gt; determines whether your request even reaches the server at all.&lt;/p&gt;

&lt;p&gt;This is why it's important to master the &lt;em&gt;Invisible Layer&lt;/em&gt; to understand caching better and know what happens under the hood, most of the library you use are built on this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Browser’s Decision Tree
&lt;/h3&gt;

&lt;p&gt;When you call &lt;code&gt;fetch('/api/user')&lt;/code&gt; for example, the browser doesn't immediately go to the internet, it goes through a strict checklist.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Memory/Disk Check:&lt;/em&gt; Do I have a copy of this locally?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Expiration Check:&lt;/em&gt; If yes, is it fresh (based on &lt;code&gt;max-age&lt;/code&gt;)?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The Short Circuit:&lt;/em&gt; If it is fresh, the browser returns the data immediately. It never talks to the server.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This behavior is controlled by the &lt;code&gt;Cache-Control&lt;/code&gt; header.&lt;/p&gt;




&lt;p&gt;Now these 3 concepts will help you understand how Caching works on the Network (HTTP) layer&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Rules: &lt;code&gt;Cache-Control&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the most important header in web performance. It tells the browser exactly how to behave.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;max-age&lt;/code&gt; (The Timer)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: max-age=3600
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the browser that "This data is good for 1 hour (3600 seconds). Do not ask the server for this data again until that time is up."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Trap&lt;/strong&gt;: If you deploy a critical bug fix 5 minutes later, users with the cached version won't see it for another 55 minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;no-cache&lt;/code&gt; vs &lt;code&gt;no-store&lt;/code&gt; (The Great Confusion)
&lt;/h4&gt;

&lt;p&gt;This is the most common interview question and production mistake regarding caching.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;no-store&lt;/code&gt; says "Never save this."&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this for sensitive data (banking info) or data that changes every millisecond.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;no-cache&lt;/code&gt; says "Go ahead and save it, but you must check with the server before using it."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now this forces the browser to ask the server, "Is this version still good?" every single time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control" rel="noopener noreferrer"&gt;MDN Web Docs: Cache-Control&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. The Receipt System: &lt;code&gt;ETags&lt;/code&gt; and &lt;code&gt;Last-modified (304)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine you have a large list of 5,000 products. You don't want to download that 2MB file every time, but you also need to know if it changed.&lt;/p&gt;

&lt;p&gt;This is where Conditional Requests come in.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For the First request&lt;/strong&gt;, server sends the data + an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag" rel="noopener noreferrer"&gt;ETag&lt;/a&gt; (a unique hash/fingerprint of the file).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For the Second request&lt;/strong&gt;, The browser sends that ETag back in a header called &lt;code&gt;If-None-Match&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;From the Server’s response&lt;/strong&gt;, If the hash is the same, the server sends a 304 Not Modified.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;The Win: You saved the user from downloading 2MB. The browser just reuses the version it already had.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. The "Stale-While-Revalidate" Strategy
&lt;/h3&gt;

&lt;p&gt;If you learn one thing from this article, let it be this. It is the gold standard for modern web performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: max-age=60, stale-while-revalidate=600
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This tells the browser:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the data is less than 60 seconds old, show it instantly (Fresh).&lt;/p&gt;

&lt;p&gt;If it's between 60 seconds and 600 seconds old, show the old data immediately, but in the background, fetch the new data and update the cache for next time (Stale-while-revalidate).&lt;/p&gt;

&lt;p&gt;This eliminates the "loading spinner" entirely while still keeping the data relatively fresh.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Deep Dive:&lt;/strong&gt; &lt;a href="https://web.dev/articles/stale-while-revalidate" rel="noopener noreferrer"&gt;web.dev: Love your cache (stale-while-revalidate)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for React Developers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You might be thinking, &lt;em&gt;"I'm a frontend dev, I don't configure server headers!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the truth, &lt;em&gt;You can't fix with JavaScript what you broke with HTTP.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your API sends &lt;code&gt;Cache-Control: no-store&lt;/code&gt;, your fancy React Query setup will struggle to maintain a cache effectively because the browser is fighting against it. If your API sends &lt;code&gt;max-age=31536000&lt;/code&gt; (1 year) for a user profile, your users will never see their profile updates.&lt;/p&gt;

&lt;p&gt;You need to check these headers in the &lt;code&gt;Chrome DevTools&lt;/code&gt; Network Tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 3 Key Takeaways:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Browser is Smart; it tries to save you work by storing files locally, so you need to know how to tell it when to stop using those files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The "Receipt" System: Instead of downloading a whole file, the browser can just ask the server, "Has this changed?" If the server says "No" (304 Not Modified), you save time and data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User Experience: Using &lt;code&gt;stale-while-revalidate&lt;/code&gt; allows your app to show old data instantly while it fetches new data in the background, eliminating need for loading spinners.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deep Dive Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you want to become a true expert on this layer, I highly recommend reading these specifications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching" rel="noopener noreferrer"&gt;MDN HTTP Caching Guide&lt;/a&gt;:&lt;/strong&gt; The comprehensive manual on how browsers handle storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://web.dev/articles/http-cache" rel="noopener noreferrer"&gt;Google's Web.dev Guide&lt;/a&gt;:&lt;/strong&gt; A practical guide on configuring headers for performance (and Lighthouse scores).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.cloudflare.com/learning/cdn/what-is-caching/" rel="noopener noreferrer"&gt;Cloudflare's CDN Learning Center&lt;/a&gt;:&lt;/strong&gt; Excellent for understanding how Edge caching (CDNs) interacts with browser caching.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What’s Next?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we understand the &lt;strong&gt;Invisible Layer&lt;/strong&gt;, we can finally move to the &lt;strong&gt;Application Layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, we will be looking at &lt;strong&gt;React Query (TanStack Query)&lt;/strong&gt;, to see how to implement an efficient caching system with it.&lt;/p&gt;

&lt;p&gt;See you in Part 3.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>frontend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Frontend Caching Handbook (Part 1)</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Thu, 12 Feb 2026 15:35:15 +0000</pubDate>
      <link>https://dev.to/peterintech/the-frontend-caching-handbook-part-1-2g30</link>
      <guid>https://dev.to/peterintech/the-frontend-caching-handbook-part-1-2g30</guid>
      <description>&lt;p&gt;I want you to imagine a scenario.&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%2Fty3idv1ezuinvcygv2qj.jpg" 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%2Fty3idv1ezuinvcygv2qj.jpg" alt="Barsita and coffee" width="256" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You walk into a coffee shop and order a Latte, the barista makes it, hands it to you and you take a sip, it tastes perfect. You turn around to grab a napkin, turn back to the counter and the latte is gone...&lt;/p&gt;

&lt;p&gt;You ask for it again. The barista sighs, grinds the beans again, steams the milk again, and hands you a new cup.&lt;/p&gt;

&lt;p&gt;This sounds ridiculous, right? Yet this is exactly how many frontend applications behave today.&lt;/p&gt;

&lt;p&gt;We fetch a list of products. The user navigates to a product detail page, then clicks "Back" only to meet a Spinner because the list is being fetched again.&lt;/p&gt;

&lt;p&gt;Welcome to Part 1 of my series on Frontend Caching. Before we dive into caching with tools like &lt;a href="https://tanstack.com/query/v4/docs/framework/react/overview" rel="noopener noreferrer"&gt;Tanstack Query&lt;/a&gt;, &lt;a href="https://redux-toolkit.js.org/tutorials/rtk-query" rel="noopener noreferrer"&gt;RTK Query&lt;/a&gt;, or &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; (which we will cover in later articles), we need to fix our mindset.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We need to stop optimizing for "easy coding" and start optimizing for "instant experiences".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Caching is Not Optional
&lt;/h2&gt;

&lt;p&gt;For a long time, caching was seen as a backend concern (Redis, database caching) or a purely "performance optimization" task you do at the end of a project.&lt;/p&gt;

&lt;p&gt;But that's not the case, Caching affects user experience and cost, so should be taken into consideration at the initial stage of building.&lt;/p&gt;

&lt;p&gt;Caching solves three specific problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Latency (The UX Killer):&lt;/strong&gt; Even on 5G, a network request takes time. Reading from memory takes nanoseconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bandwidth (The Cost Killer):&lt;/strong&gt; Why download the same 500KB JSON payload five times in one session? Those extra requests are costing unnecessary extra money&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Load (The Scale Killer):&lt;/strong&gt; Your backend engineers will thank you if you stop hammering the API for data that hasn't changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Core Concept: Fresh vs Stale Data
&lt;/h2&gt;

&lt;p&gt;To understand caching, you must understand the concept of Staleness.&lt;/p&gt;

&lt;p&gt;In a perfect world, our frontend would always be perfectly synced with the database. But the moment you fetch data to the client, it is technically &lt;code&gt;stale&lt;/code&gt;. Something could have changed on the server the millisecond after your request finished.&lt;/p&gt;

&lt;p&gt;Hence, Caching is the art of accepting staleness for a defined period.&lt;/p&gt;

&lt;p&gt;This is the mental shift, instead of asking: "Is this data perfectly up to date?" You should ask: "Is this data fresh enough for the user right now?"&lt;/p&gt;

&lt;p&gt;If I’m looking at a list of blog posts, does it matter if a new post was added 2 seconds ago? Probably not! I can show the cached list instantly as that data is &lt;code&gt;stale&lt;/code&gt; but acceptable.&lt;/p&gt;

&lt;p&gt;But If I’m looking at my bank account balance? That better be &lt;code&gt;fresh&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Layers of Caching
&lt;/h2&gt;

&lt;p&gt;As frontend engineers, we usually deal with three distinct layers. Understanding where your data lives is half the battle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Browser Cache (HTTP)&lt;/strong&gt;&lt;br&gt;
This is the invisible layer. Before your React or Vue code even runs, the browser checks if it already has the resource. This is controlled by HTTP headers (Cache-Control, ETag and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers" rel="noopener noreferrer"&gt;likes&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Browser Cache is usually automatic if configured correctly on the server, though hard to manipulate manually from JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. The CDN / Edge Cache&lt;/strong&gt;&lt;br&gt;
This lives between your user and your server. It stores copies of your content closer to the user geographically.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One advantage is fast delivery of static assets, though if you cache dynamic API responses here, you risk showing different user different data which can be a nightmare to debug&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. Application Memory (The Client State)&lt;/strong&gt;&lt;br&gt;
This is where we will focus most of this series. This is using &lt;code&gt;React Query&lt;/code&gt;, &lt;code&gt;RTK Query&lt;/code&gt; and the likes, or even a simple object in your code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here you have instant access and complete control over invalidation logic. Though it vanishes when the user refreshes the page (unless you persist it).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Hardest Problem in Computer Science - Invalidation
&lt;/h2&gt;

&lt;p&gt;You’ve likely heard the quote by Phil Karlton:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are only two hard things in Computer Science: cache invalidation and naming things.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Invalidation is knowing when to delete the cache.&lt;/p&gt;

&lt;p&gt;Imagine you cache a &lt;code&gt;User Profile&lt;/code&gt;. The user updates their name on a &lt;code&gt;Settings&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;You send the PUT request to update the name.&lt;/p&gt;

&lt;p&gt;The server confirms it's updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Trap is this:&lt;/strong&gt; You navigate back to the &lt;code&gt;Profile&lt;/code&gt; page, and your cache still holds the old name now the user thinks the app is broken.&lt;/p&gt;

&lt;p&gt;You have to tell the cache: "Hey, the data associated with &lt;code&gt;User Profile&lt;/code&gt; is now dirty. Fetch it again next time."&lt;/p&gt;

&lt;p&gt;Technology has evolved so well that we have tools that aids us build better performant web applications...&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;In this series, we'll be moving from "No idea" to "Master". We aren't just going to learn how to use the tools; we are going to learn why they work the way they do.&lt;/p&gt;

&lt;p&gt;Here is the roadmap:&lt;/p&gt;

&lt;p&gt;Part 2: The Invisible Layer – Mastering HTTP Headers (because you can't fix with JS what you broke with Headers).&lt;/p&gt;

&lt;p&gt;Part 3: The State Manager Revolution – deep dive into Tanstack Query.&lt;/p&gt;

&lt;p&gt;Part 4: The Redux Powerhouse – Implementation with RTK Query.&lt;/p&gt;

&lt;p&gt;Part 5: The Full Stack – Server-side caching in Next.js.&lt;/p&gt;

&lt;p&gt;See you in Part 2.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Beyond Clean Code: Mastering Parallel Data Fetching with React Router's defer</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Tue, 23 Dec 2025 16:04:55 +0000</pubDate>
      <link>https://dev.to/peterintech/beyond-clean-code-mastering-parallel-data-fetching-with-react-routers-defer-4d1b</link>
      <guid>https://dev.to/peterintech/beyond-clean-code-mastering-parallel-data-fetching-with-react-routers-defer-4d1b</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/peterintech/stop-writing-messy-states-why-i-swapped-useeffect-for-react-router-loaders-46mm"&gt;previous post&lt;/a&gt;, I discussed how to get rid of Messy State by moving from &lt;code&gt;useEffect&lt;/code&gt; to &lt;code&gt;React Router Loaders&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We successfully cleaned up our components, but we introduced a new challenge; The "Waiting Game."&lt;/p&gt;

&lt;p&gt;Because standard Loaders fetch data before the route renders, if your API takes 3 seconds to respond, your user is stuck looking at the old page until that loader finishes. To the user, it feels like the app is frozen or the link is broken.&lt;/p&gt;

&lt;p&gt;Today, we solve that with the &lt;a href="https://reactrouter.com/6.30.2/guides/deferred" rel="noopener noreferrer"&gt;Defer Pattern&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Understanding the Logic: What exactly is "defer"?&lt;/h2&gt;

&lt;p&gt;To understand defer, you have to think about how a normal &lt;code&gt;loader&lt;/code&gt; works. Usually, a &lt;code&gt;loader&lt;/code&gt; is like a waiter who won't leave the kitchen until every single dish in your order is cooked. If the steak takes 20 minutes, you don't even get your water until the steak is done.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;defer&lt;/code&gt; changes the rules. It allows the waiter to bring the water and appetizers (Fast Data) immediately, while the steak (Slow Data) is still cooking.&lt;/p&gt;

&lt;h4&gt;The Magic of the Promise&lt;/h4&gt;

&lt;p&gt;When you use &lt;code&gt;defer&lt;/code&gt;, you aren't returning raw data; you are returning a Promise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Loader: Tells React Router, "Here is some data I have now, and here is a 'ticket' (the promise) for data that is coming later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Component: Renders immediately. It doesn't wait for that "ticket" to resolve.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Implementation: v6 vs v7&lt;/h2&gt;

&lt;p&gt;For &lt;code&gt;v6&lt;/code&gt;, to make this work, we need a three-part harmony: the &lt;code&gt;defer&lt;/code&gt; utility, the &lt;code&gt;&amp;lt;Await&amp;gt;&lt;/code&gt; component, and React's built-in &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt;.&lt;br&gt;
However, React Router recently evolved, in &lt;code&gt;v7&lt;/code&gt;, we don't need &lt;code&gt;defer&lt;/code&gt; as the router is smart enough to handle promises automatically.&lt;/p&gt;

&lt;h4&gt;Step 1: Edit the Loader&lt;/h4&gt;

&lt;p&gt;Instead of using await for every fetch, we only await the critical data.&lt;/p&gt;

&lt;p&gt;In React Router v6&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;// for v6.4+ we use the "defer"&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;defer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// CRITICAL DATA: We `await` this. The page won't load until we have them.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;productReq&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="c1"&gt;// NON-CRITICAL DATA: No `await` here! We pass the promise directly.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reviewsPromise&lt;/span&gt; &lt;span class="o"&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/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&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;/reviews`&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reviewsPromise&lt;/span&gt; 
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In React Router v7&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;// for v7 we use don't use the "defer"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// CRITICAL DATA: We `await` this. The page won't load until we have them.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;productReq&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="c1"&gt;// NON-CRITICAL DATA: No `await` here! We pass the promise directly.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reviewsPromise&lt;/span&gt; &lt;span class="o"&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/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&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;/reviews`&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reviewsPromise&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;h4&gt;Step 2: The UI (Unwrapping the Promise)&lt;/h4&gt;

&lt;p&gt;Regardless of which version you use, the UI implementation is the same.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;reviews&lt;/code&gt; is a Promise, we can't just &lt;code&gt;.map()&lt;/code&gt; over it instantly. We use the &lt;code&gt;&amp;lt;Await&amp;gt;&lt;/code&gt; component to "unwrap" it once it arrives.&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;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Await&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&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;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&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;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLoaderData&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;div&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;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;product&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="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Renders&lt;/span&gt; &lt;span class="nx"&gt;instantly&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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="nx"&gt;reviews&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;/p&amp;gt;}&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;Await&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;errorElement&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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="nx"&gt;loading&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;resolvedReviews&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&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;resolvedReviews&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;r&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;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;r&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comment&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;/li&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&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;/Await&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="sr"&gt;/Suspense&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="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;Why this is a UX Game Changer&lt;/h2&gt;

&lt;h4&gt;1. Faster Perceived Performance&lt;/h4&gt;

&lt;p&gt;The user sees the "shell" of the page and the primary content almost instantly. They can start reading the product description while the reviews are still "streaming" in over the wire.&lt;/p&gt;

&lt;h4&gt;2. No more "All-or-Nothing" UI&lt;/h4&gt;

&lt;p&gt;In the old &lt;code&gt;useEffect&lt;/code&gt; days, if one API call failed, you often ended up with a giant error screen. With &lt;code&gt;&amp;lt;Await&amp;gt;&lt;/code&gt;, you get an &lt;code&gt;errorElement&lt;/code&gt; property. If the reviews fail, only that section shows an error. The rest of your page stays functional.&lt;/p&gt;

&lt;h4&gt;3. Better than "Global" Loading Spinners&lt;/h4&gt;

&lt;p&gt;Instead of a giant spinner that covers the whole screen, you can use Skeleton Screens in your fallback to reserve space, preventing that annoying "layout shift" when data pops in.&lt;/p&gt;

&lt;h2&gt;When to defer and when not to&lt;/h2&gt;

&lt;p&gt;Since the focus is user experience, wrong use can act against the goal&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Scenario&lt;/th&gt;
      &lt;th&gt;Use Standard await&lt;/th&gt;
      &lt;th&gt;Use defer&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Crucial Data (SEO/Meta tags)&lt;/td&gt;
      &lt;td&gt;✅ Yes&lt;/td&gt;
      &lt;td&gt;❌ No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fast APIs (&amp;lt; 200ms)&lt;/td&gt;
      &lt;td&gt;✅ Yes&lt;/td&gt;
      &lt;td&gt;❌ No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Slow Analytics/Logs&lt;/td&gt;
      &lt;td&gt;❌ No&lt;/td&gt;
      &lt;td&gt;✅ Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Secondary Page Content&lt;/td&gt;
      &lt;td&gt;❌ No&lt;/td&gt;
      &lt;td&gt;✅ Yes&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;Introducing &lt;code&gt;Loaders&lt;/code&gt; cleaned up our code in &lt;a href="https://dev.to/peterintech/stop-writing-messy-states-why-i-swapped-useeffect-for-react-router-loaders-46mm"&gt;Part 1&lt;/a&gt;, but &lt;code&gt;defer&lt;/code&gt; makes our apps feel like professional-grade software. By strategically choosing what data to wait for and what data to stream, you give your users a snappier, more reliable experience.&lt;/p&gt;

&lt;p&gt;What’s your favorite way to improve user experience? Let me know in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
      <category>ux</category>
    </item>
    <item>
      <title>Stop Writing Messy States: Why I Swapped useEffect for React Router Loaders</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Thu, 18 Dec 2025 14:33:49 +0000</pubDate>
      <link>https://dev.to/peterintech/stop-writing-messy-states-why-i-swapped-useeffect-for-react-router-loaders-46mm</link>
      <guid>https://dev.to/peterintech/stop-writing-messy-states-why-i-swapped-useeffect-for-react-router-loaders-46mm</guid>
      <description>&lt;p&gt;We have all been there... You create a new component, and the first thing you do is set up the trinity of data fetching state:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;loading&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then, you write the inevitable &lt;code&gt;useEffect&lt;/code&gt; hook. It usually looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="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;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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;response&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;Network response was not ok&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="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="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;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;Spinner&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;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;ErrorMessage&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;The Problem:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Boilerplate&lt;/strong&gt;: We just wrote 20 lines of code just to get data from A to B.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render-then-Fetch&lt;/strong&gt;: The component has to mount (render) first before the effect kicks in to start fetching. This causes a &lt;a href="https://remix.run/blog/remixing-react-router" rel="noopener noreferrer"&gt;waterfall effect&lt;/a&gt; and slower perceived performance.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;State Management Hell&lt;/strong&gt;: You are manually managing loading and error states in every single component that needs data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Solution: React Router Loaders introduced in v6&lt;/h2&gt;

&lt;p&gt;React Router v6.4+ introduced a paradigm shift: &lt;strong&gt;Loaders&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Loaders&lt;/strong&gt; are a part of the &lt;a href="https://reactrouter.com/6.30.2/routers/picking-a-router#data-apis" rel="noopener noreferrer"&gt;Data APIs&lt;/a&gt; which lets you handle data fetching, actions/mutations and error handling directly in your route definitions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea is simple: &lt;strong&gt;Fetch-then-Render&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of the component asking for data after it mounts, the Router fetches the data before it renders the component. If the data isn't ready, the component doesn't load. If there is an error, the Router handles it elsewhere.&lt;/p&gt;

&lt;p&gt;Here is how to clean up your code in 3 steps:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's assumed you're working on a react application with react-router installed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Step 1: Setup Router that supports Data APIs&lt;/h3&gt;

&lt;p&gt;This will involve reconfiguring the router setup see &lt;a href="https://reactrouter.com/6.30.2/routers/picking-a-router" rel="noopener noreferrer"&gt;Picking a Router&lt;/a&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;//App.jsx&lt;/span&gt;

&lt;span class="c1"&gt;// From this&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;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BrowserRouter&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;Routes&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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="sr"&gt;/Routes&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="sr"&gt;/BrowserRouter&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//To this&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;RouterProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;element&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;UserProfile&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouterProvider&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;Step 2: Write a loader function&lt;/h3&gt;

&lt;p&gt;You define a function that fetches your 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="c1"&gt;// utils.js&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;userLoader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Could not fetch user details&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;Step 3: Connect it to the Route&lt;/h3&gt;

&lt;p&gt;In your Router configuration (using &lt;code&gt;createBrowserRouter&lt;/code&gt;), you plug the loader directly into the route.&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;// App.jsx&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;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RouterProvider&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-router-dom&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;userLoader&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;./utils&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="nx"&gt;UserProfile&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;./user&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="nx"&gt;ErrorPage&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;./errorPage&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;element&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;UserProfile&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;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userLoader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// &amp;lt;--- The magic happens here&lt;/span&gt;
    &lt;span class="na"&gt;errorElement&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;ErrorPage&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;--- Handles errors automatically!&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;RouterProvider&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;Step 3: Consume the Data&lt;/h3&gt;

&lt;p&gt;Now, look at how clean your component becomes. No &lt;code&gt;useEffect&lt;/code&gt;, No &lt;code&gt;useState&lt;/code&gt; for loading or errors. Just one hook: &lt;code&gt;useLoaderData&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;// user.jsx&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;useLoaderData&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-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Data is already here!&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;div&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;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&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;p&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;email&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;/p&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="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In the ErrorPage, you can get error message and handle error by grabbing the &lt;code&gt;useRouteError&lt;/code&gt; hook from "react-router", implementation is similar to &lt;code&gt;useLoaderData&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Why this is Clean Code?&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; Your UI component is responsible for UI, not fetching logic. The fetching logic lives in the loader.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Error Handling:&lt;/strong&gt; If the API fails, React Router catches the error and renders the &lt;code&gt;errorElement&lt;/code&gt; defined in the route. Hence, your component doesn't need to check if (error).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; The browser starts fetching the data as soon as the user clicks the link, in parallel with loading the code for the new page.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is a powerful tool but using it for data fetching in 2025 is often unnecessary complexity. By switching to Loaders, you delete code, prevent bugs, and make your application feel snappier.&lt;/p&gt;

&lt;p&gt;Give your &lt;code&gt;useEffect&lt;/code&gt; a break and let the Router do the heavy lifting.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>cleancode</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Understanding APIs and Streamlining Development with Postman</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Fri, 08 Dec 2023 12:33:47 +0000</pubDate>
      <link>https://dev.to/peterintech/understanding-apis-and-streamlining-development-with-postman-384a</link>
      <guid>https://dev.to/peterintech/understanding-apis-and-streamlining-development-with-postman-384a</guid>
      <description>&lt;p&gt;In the digital age, APIs (Application Programming Interfaces) serve as the backbone of modern software development, enabling seamless communication between different applications, services, and systems. They facilitate the exchange of data and functionalities, allowing developers to create innovative solutions from an already existing structure.&lt;br&gt;
In this blog post, we are going to look at the foundational concepts of APIs, their importance in development and how &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;postman&lt;/a&gt; came in to revolutionize api testing and streamlined development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an API?
&lt;/h2&gt;

&lt;p&gt;As the name implies, Application Programming Interface defines the rules and protocols that enable different software applications to communicate with each other. It acts as an intermediary, allowing one piece of software to access and interact with another.&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%2F10kiowfjskeq9m78j3h9.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%2F10kiowfjskeq9m78j3h9.png" alt=" " width="768" height="307"&gt;&lt;/a&gt;&lt;br&gt;
A simple analogy of how apis work is just like a traditional restaurant where you step in and you place your order through the waiter and the waiter gets your order to the kitchen and returns with your order. In this analogy, the waiter is the api, the customer is the client/user and the Kitchen is the server. In other words, apis basically act as an intermediary to allow one piece of software to access and interact with another, they make this possible without revealing the codebase or database of the server, &lt;em&gt;you get what your ask for&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;APIs have a versatile area of applications not limited to softwares alone, we also have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardware APIs&lt;/strong&gt;: These are software that allow you to interact with hardware components, for example, a printer API lets your software communicate with the printer to produce physical copies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Software Library APIs&lt;/strong&gt;: These provide pre-built functions and routines that developers can use to perform specific tasks, they embed complex functionalities, this helps to save a bunch of time!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web APIs:&lt;/strong&gt; This is perhaps the most common type, they enable communication between different web services. They allow you to fetch data from a remote server, like a restaurant offering takeout service from its menu. This will be the focus for today.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;APIs come in various types, including &lt;em&gt;RESTful APIs, SOAP APIs, and GraphQL&lt;/em&gt;, each with its own specifications and purposes. The mostly used is the RESTful API&lt;/p&gt;

&lt;h3&gt;
  
  
  The Importance of APIs in Development
&lt;/h3&gt;

&lt;p&gt;The significance of APIs in modern development cannot be overstated. They offer several key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; APIs allow disparate systems to seamlessly work together, fostering interoperability and enabling the creation of integrated solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; Developers can leverage existing APIs to access functionalities or data, reducing development time and effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; APIs provide a scalable foundation for applications, allowing them to adapt and grow as requirements change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Innovation:&lt;/strong&gt; APIs empower developers to build upon existing services and functionalities, encouraging innovation and the creation of new products.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Anatomy of an API call
&lt;/h3&gt;

&lt;p&gt;Understanding an API call involves grasping several key components and considerations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; The URL that specifies the location and resource being accessed or manipulated. It determines where the API request is sent. Each api has a unique endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTTP Method (HTTP Verb):&lt;/strong&gt; - Indicates the type of action being performed on the resource (GET, POST, PUT, DELETE, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; Additional information sent with the request, including authentication tokens, content types, or metadata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; Query parameters or request body data (in the case of POST, PUT, PATCH) sent along with the request to provide additional information or modify the request. To learn more, visit: &lt;a href="https://www.restapitutorial.com/lessons/httpmethods.html" rel="noopener noreferrer"&gt;HTTP verbs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt; If required, methods for authenticating the requester's identity, such as API keys, OAuth tokens, or other authentication mechanisms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; The data returned by the API call, typically in JSON or XML format. It includes the requested information or an acknowledgment of the action performed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Status Codes:&lt;/strong&gt; Indicate the success or failure of the request, each code has a unique message, be it success or failure (e.g., 200 for success, 404 for not found, 500 for server errors). To learn more about status code, visit: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" rel="noopener noreferrer"&gt;Status Code MDN&lt;/a&gt;&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Introducing Postman
&lt;/h2&gt;

&lt;p&gt;Amidst the varieties of tools available for API development and testing, Postman stands out as a powerful and user-friendly option. It offers a comprehensive suite of features that streamline the API development lifecycle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Benefits of Postman:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User-Friendly Interface:&lt;/strong&gt; Postman's intuitive interface simplifies the process of designing, testing, and debugging APIs, making it accessible for both beginners and seasoned developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; It facilitates team collaboration by allowing seamless sharing of API collections, environments, and tests, enabling efficient teamwork and knowledge sharing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Testing:&lt;/strong&gt; Postman enables the creation of automated tests, ensuring the reliability and consistency of APIs across different environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation:&lt;/strong&gt; With its documentation capabilities, Postman assists in generating comprehensive API documentation, simplifying the process of understanding and consuming APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mock Servers:&lt;/strong&gt; Developers can create mock servers to simulate API endpoints, allowing for testing without depending on the actual backend implementation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;APIs serve as the backbone of interconnected digital ecosystems, enabling the creation of robust and innovative applications. Among the tools available for API development and testing, Postman emerges as a versatile solution, empowering developers to streamline their workflow, enhance collaboration, and build reliable APIs efficiently.&lt;/p&gt;

&lt;p&gt;In conclusion, understanding the importance of APIs and harnessing the capabilities of tools like &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; can significantly contribute to the success and efficiency of software development endeavors in today's interconnected world.&lt;/p&gt;

</description>
      <category>postman</category>
      <category>postmanunleased</category>
      <category>postmanstudentexpert</category>
      <category>api</category>
    </item>
    <item>
      <title>CRUD Todo App - React and Redux-toolkit</title>
      <dc:creator>Peter Ogbonna</dc:creator>
      <pubDate>Tue, 18 Apr 2023 02:25:09 +0000</pubDate>
      <link>https://dev.to/peterintech/crud-todo-app-react-and-redux-toolkit-2708</link>
      <guid>https://dev.to/peterintech/crud-todo-app-react-and-redux-toolkit-2708</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We’ll make a simple Todo-list app that performs all four CRUD (Create, Read, Update, Delete) operations- on the front-end, using React and Redux-Toolkit: &lt;a href="https://todo-beige-tau.vercel.app/" rel="noopener noreferrer"&gt;live link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are familiar with Redux you can jump straight to the Implementation &lt;/p&gt;

&lt;p&gt;What to get in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Redux?&lt;/li&gt;
&lt;li&gt;Redux vs Redux-Toolkit&lt;/li&gt;
&lt;li&gt;How Redux Works&lt;/li&gt;
&lt;li&gt;Implementation&lt;/li&gt;
&lt;li&gt;
Helpful Links &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Redux?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://redux.js.org" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; is a state management library, that helps centralize your application’s state and logic. It comes with a DevTool which makes it easy to trace when, where, why and how your application’s state changed.&lt;br&gt;
It works with any UI layer and popularly used with Reactjs.&lt;br&gt;
And you might be wondering, what’s the difference between Redux and Redux-Toolkit, let’s take a look at that.&lt;/p&gt;
&lt;h2&gt;
  
  
  Redux vs ReduxToolkit
&lt;/h2&gt;

&lt;p&gt;Redux is the core library for managing application state, while Redux-Toolkit is a companion library that provides additional utilities for working with Redux. You can use Redux on its own, but many developers find that Redux-Toolkit makes it even easier and more efficient to work with Redux even the Redux team recommends Redux-Toolkit as the approach for writing Redux logic, because it is a newer library that provides a set of utilities for working with Redux. It provides a simpler API for common tasks, as well as performance optimizations that can help to improve the performance of your application for example, the library uses Immer under the hood to provide immutable updates to the store, which can help to avoid unnecessary re-renders. Redux-Toolkit comes with functions for creating and managing Redux stores, as well as middleware for handling asynchronous actions, this can help to make your code more organized and maintainable. &lt;br&gt;
Simply put, Redux-Toolkit is designed to make it easier and more efficient to write Redux applications&lt;/p&gt;
&lt;h2&gt;
  
  
  How Redux works
&lt;/h2&gt;

&lt;p&gt;In Redux, you basically create an action and dispatch the action using the usedispatch hook.&lt;br&gt;
Redux provides a predictable state container that helps manage the state of your application in a centralized manner, a store. A “store” is a container that retains your application’s global state, each component can access the store without having to send down props from one component to another. &lt;/p&gt;
&lt;h3&gt;
  
  
  The five major terminologies in Redux:
&lt;/h3&gt;

&lt;p&gt;In major Redux applications you’ll find these major components working hand in hand. I will give brief explanation of each of these terminologies, it might not be clear enough, but follow through, while building our app it will become clearer. We’ll briefly discuss the main terminologies in a typical Redux app&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Store:&lt;/b&gt; A single source of truth that holds the entire state tree of your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Actions:&lt;/b&gt; Actions are the medium used to send data from your application to your Redux store, they are plain JavaScript objects that represent an intention to change the state, they contain a type property that describes the action as well as a payload (an additional data necessary to carryout the action) to update the state. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Reducers:&lt;/b&gt; Reducers are Pure functions that take the current state and an action and return a new state. They should not modify the current state directly, but instead return a new state object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p id="dispatch"&gt;&lt;b&gt;Dispatch:&lt;/b&gt; To update the state, an action must be dispatched to the store using the `dispatch` function. This triggers the store to call the corresponding reducer function with the current state and the dispatched action. Just think of the `dispatch` function as `setState`&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p id="selector"&gt;&lt;b&gt;Selector:&lt;/b&gt; To access data from the store. We do this by using the `useSelector` hook from react-redux &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just think of Dispatch and Selector as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Grey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Dispatch (update the state)&lt;/span&gt;
&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Selector (get the state)&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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;To get started, you only need two npm packages&lt;br&gt;
&lt;code&gt;npm install @reduxjs/toolkit react-redux&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a Redux Store
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;src/redux/store.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&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;@reduxjs/toolkit&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:{},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the Redux Store to Index.js parent file
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;src/index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&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-redux&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;store&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;./redux/store&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&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="sr"&gt;/Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When done importing these necessary components, ensure to wrap your  component with the provider and include the store you added recently, this enables your whole app to access the Redux store&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Slice
&lt;/h3&gt;

&lt;p&gt;Of course, Redux- Toolkit introduced slice. A slice is a part of the application’s state that can be updated independently. It contains a set of actions and a reducer that handles those actions. Think of a slice as a certain feature you want to apply different action to it, on different occasions, now each action in the feature (slice) uses the same state, having initial value of  &lt;code&gt;initialState&lt;/code&gt;. In this app, I have 3 actions running in the same slice. All the actions reside in the reducers object&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/redux/reducer.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSlice&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;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&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;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;reducers&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, we can go ahead to add our slice Reducers to the store in &lt;code&gt;src/redux/store.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&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;@reduxjs/toolkit&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./reducer&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the basic configuration needed using Redux-toolkit, we are ready to go Redux baby! &lt;br&gt;
Let’s go about creating actions in &lt;code&gt;src/redux/reducer.js&lt;/code&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  To Add Note
&lt;/h4&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;createSlice&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;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&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;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Adding new todo&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;export&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;addTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&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;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;state&lt;/code&gt; is the current state, with initial value of &lt;code&gt;initialState&lt;/code&gt;, action.payload is the value passed into the addTodo function in &lt;code&gt;src/components/TextField/TextField.jsx&lt;/code&gt;&lt;br&gt;
We use our actions to work with the store with the help of the useDispatch hook from react-redux, this is how we &lt;strong&gt;Dispatch&lt;/strong&gt; as explained earlier&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/components/TextField/TextField.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addTodo&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;../../redux/reducer&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;useDispatch&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-redux&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;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;addTodo&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;addTodo&lt;/code&gt; action takes in the value passed in, which is an object of two key: value pairs and adds it to the array, hence updating the state. Therefore making the state an array of objects with two keys: id and text.&lt;/p&gt;




&lt;h4&gt;
  
  
  To Delete Note:
&lt;/h4&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;createSlice&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;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&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;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Adding new todo&lt;/span&gt;
&lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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="err"&gt; &lt;/span&gt; &lt;span class="err"&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
 &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="na"&gt;deleteTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&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="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;export&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;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deleteTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&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;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;deleteTodo&lt;/code&gt; function checks for a matching id to the one passed in through our dispatch function, to update the state, while removing the matched id from the array&lt;br&gt;
Here, the &lt;code&gt;action.payload&lt;/code&gt; is &lt;code&gt;id&lt;/code&gt;&lt;br&gt;
from &lt;code&gt;src/components/Note/Note.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;deleteTodo&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;../../redux/reducer&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;useDispatch&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-redux&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;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deleteTodo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Update Note:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;updateTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="nx"&gt;todo&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="err"&gt; &lt;/span&gt; &lt;span class="err"&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &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="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="err"&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;The &lt;code&gt;updateTodo&lt;/code&gt; function updates the value of a selected item from the array of objects(different list items), then updates it’s &lt;code&gt;item&lt;/code&gt; value by the text.&lt;/p&gt;

&lt;p&gt;This function takes an object of two key value pairs as seen in &lt;code&gt;src/components/Note/Note.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updateTodo&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;../../redux/reducer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;updateTodo&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; is a numeric value used to identify an item from the list, the text is a string used to update the text of the identified item.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access the state
&lt;/h2&gt;

&lt;p&gt;This is where &lt;strong&gt;selector&lt;/strong&gt; comes in, as explained earlier we use it by using the &lt;code&gt;useSelector&lt;/code&gt; hook from &lt;code&gt;react-redux&lt;/code&gt;. It helps us extract data from the Redux store state, using a selector function&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;useSelector&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-redux&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="nx"&gt;Note&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;../Note/Note&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;ShowTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;list&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="p"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Note&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
 &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
 &lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ShowTodo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that is how we access data from our store.&lt;br&gt;
Hope you got value!&lt;/p&gt;

&lt;h2&gt;
  
  
  Helpful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/iampitrus/todo" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://todo-beige-tau.vercel.app/" rel="noopener noreferrer"&gt;Live Preview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>redux</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
