<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ State Management  - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ State Management  - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 24 Aug 2026 10:22:50 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/state-management/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Shared State Complexity in React – A Complete Handbook for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Imagine you're building a simple shopping website. You have a product page where users can add items to their cart, and a header that displays the number of items in the cart. Sounds simple, right? But here's the challenge: how does the header know w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/shared-state-complexity-in-react-handbook/</link>
                <guid isPermaLink="false">688bfc51bf96ff93c962d1f2</guid>
                
                    <category>
                        <![CDATA[ #reactstate ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Henry Adepegba ]]>
                </dc:creator>
                <pubDate>Thu, 31 Jul 2025 23:29:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754003865317/3c91ac36-2e1b-4e03-ac54-64a100e44c8f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine you're building a simple shopping website. You have a product page where users can add items to their cart, and a header that displays the number of items in the cart. Sounds simple, right? But here's the challenge: <strong>how does the header know when someone adds an item on a completely different part of the page?</strong></p>
<p>This is the <strong>shared state problem</strong>, which occurs when different parts of your application need to access and update the same information. In small apps, this isn't a big deal. But as your app grows, managing shared state becomes one of the most complex and frustrating parts of React development.</p>
<p>In this handbook, you'll learn:</p>
<ul>
<li><p>What props and prop drilling are, and why they become problematic</p>
</li>
<li><p>How to recognize when you have a shared state problem</p>
</li>
<li><p>Multiple solutions to manage shared state effectively</p>
</li>
<li><p>When to use each solution</p>
</li>
<li><p>How to avoid common mistakes that even experienced developers make</p>
</li>
</ul>
<p>By the end, you'll understand how to build React applications that stay organized and maintainable as they grow.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-well-cover">What we’ll cover:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites-what-you-should-know-before-reading-this-guide">Prerequisites: What You Should Know Before Reading This Guide</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-essential-react-knowledge">Essential React Knowledge</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-javascript-prerequisites">JavaScript Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-concepts-youll-encounter">React Concepts You'll Encounter</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-development-environment">Development Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conceptual-understanding">Conceptual Understanding</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-you-dont-need-to-know">What You DON'T Need to Know</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-self-assessment-questions">Self-Assessment Questions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-recommended-preparation">Recommended Preparation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-this-guide-will-teach-you">What This Guide Will Teach You</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-building-blocks-props-in-react">Understanding the Building Blocks: Props in React</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-props">What are props?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-more-modern-way-destructuring-props">A more modern way: Destructuring props</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-prop-drilling-and-why-is-it-a-problem">What is Prop Drilling and Why is it a Problem?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-a-simple-example-passing-a-username">A simple example: Passing a username</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-realistic-example-shopping-cart-prop-drilling">A realistic example: Shopping cart prop drilling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-does-this-happen-and-get-worse">Why does this happen and get worse</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-1-react-context-api-understanding-the-concept">Solution 1: React Context API – Understanding the Concept</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-radio-station-analogy">The radio station analogy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-createcontext">What is createContext()?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-a-basic-context-provider">Creating a basic Context Provider</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-usecontext-hook">Understanding the useContext hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-a-custom-hook-for-cleaner-usage">Creating a custom hook for cleaner usage</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-putting-it-all-together-complete-context-example">Putting it all together: Complete Context example</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-context-patterns-and-concepts">Advanced Context Patterns and Concepts</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-multiple-contexts-for-separation-of-concerns">Multiple contexts for separation of concerns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-usereducer-for-complex-state-logic">Understanding useReducer for complex state logic</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-2-state-management-libraries-explained">Solution 2: State Management Libraries Explained</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-understanding-redux-the-predictable-state-container">Understanding Redux: The predictable state container</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-redux-toolkit-modern-redux-made-simple">Redux Toolkit: Modern Redux made simple</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-zustand-simple-and-flexible-state-management">Zustand: Simple and flexible state management</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-performance-optimization-strategies-explained">Performance Optimization Strategies Explained</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-do-unnecessary-re-renders-happen">Why do unnecessary re-renders happen?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-1-split-contexts-to-minimize-re-renders">Solution 1: Split contexts to minimize re-renders</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-2-memoize-context-values-to-prevent-object-recreation">Solution 2: Memoize context values to prevent object recreation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-3-select-only-what-you-need">Solution 3: Select only what you need</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-4-use-reactmemo-for-expensive-components">Solution 4: Use React.memo for expensive components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-solution-5-optimize-with-custom-selector-hooks">Solution 5: Optimize with custom selector hooks</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-shared-state-a-comprehensive-approach">Testing Shared State: A Comprehensive Approach</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-shared-state-testing-is-different">Why shared state testing is different</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-react-context">Testing React Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-redux-stores">Testing Redux stores</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-each-approach-a-decision-framework">When to Use Each Approach: A Decision Framework</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-decision-tree-for-state-management">Decision tree for state management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-detailed-comparison-of-approaches">Detailed comparison of approaches</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-examples-of-when-to-use-each">Real-world examples of when to use each</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-common-pitfalls-and-how-to-avoid-them">Common Pitfalls and How to Avoid Them</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-pitfall-1-context-hell-too-many-nested-providers">Pitfall 1: Context hell (too many nested providers)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pitfall-2-massive-context-values-causing-unnecessary-re-renders">Pitfall 2: Massive context values causing unnecessary re-renders</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pitfall-3-not-memoizing-context-values">Pitfall 3: Not memoizing context values</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pitfall-4-prop-drilling-when-context-would-be-better">Pitfall 4: Prop drilling when Context would be better</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pitfall-5-using-global-state-for-everything">Pitfall 5: Using global state for everything</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pitfall-6-not-handling-loading-and-error-states-in-shared-state">Pitfall 6: Not handling loading and error states in shared state</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-maintainable-shared-state">Best Practices for Maintainable Shared State</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-use-consistent-naming-conventions">1. Use consistent naming conventions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-group-related-state-and-actions-together">2. Group related state and actions together</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-create-selector-hooks-for-complex-data-access">3. Create selector hooks for complex data access</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-handle-side-effects-properly">4. Handle side effects properly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-implement-proper-error-boundaries">5. Implement proper error boundaries</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-building-maintainable-react-applications">Conclusion: Building Maintainable React Applications</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-summary-of-approaches">Summary of approaches</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-principles-to-remember">Key principles to remember</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-evolution-of-a-typical-application">The evolution of a typical application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-recommendations">Final recommendations</a></p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-prerequisites-what-you-should-know-before-reading-this-guide">Prerequisites: What You Should Know Before Reading This Guide</h2>
<h3 id="heading-essential-react-knowledge">Essential React Knowledge</h3>
<p><strong>React Fundamentals (Required)</strong></p>
<ul>
<li><p><strong>Functional components</strong>: You should be comfortable writing and using React functional components</p>
</li>
<li><p><strong>JSX syntax</strong>: Understanding how to write JSX, use curly braces for JavaScript expressions, and handle events</p>
</li>
<li><p><strong>Basic props</strong>: Know how to pass and receive props between parent and child components</p>
</li>
<li><p><strong>useState hook</strong>: You should understand how <code>useState</code> works, including state updates and re-renders</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// You should be comfortable with code like this:</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params">{ title }</span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;
        Increment
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>useEffect Hook (Recommended)</strong></p>
<ul>
<li><p>Basic understanding of side effects in React</p>
</li>
<li><p>When and why to use <code>useEffect</code></p>
</li>
<li><p>How dependency arrays work</p>
</li>
<li><p>This helps with understanding performance optimization sections</p>
</li>
</ul>
<h3 id="heading-javascript-prerequisites">JavaScript Prerequisites</h3>
<p><strong>ES6+ Features (Required)</strong></p>
<ul>
<li><p><strong>Arrow Functions</strong>: <code>const myFunc = () =&gt; {}</code></p>
</li>
<li><p><strong>Destructuring</strong>: <code>const { name, age } = person</code> and <code>const [first, second] = array</code></p>
</li>
<li><p><strong>Spread Operator</strong>: <code>...array</code> and <code>...object</code></p>
</li>
<li><p><strong>Template Literals</strong>: Using backticks and <code>${variable}</code> syntax</p>
</li>
<li><p><strong>Array methods</strong>: <code>map()</code>, <code>filter()</code>, <code>find()</code>, <code>reduce()</code> - these appear frequently in state updates</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// You should understand this syntax:</span>
<span class="hljs-keyword">const</span> newItems = [...existingItems, newItem];
<span class="hljs-keyword">const</span> { name, price } = product;
<span class="hljs-keyword">const</span> updatedItems = items.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> 
  item.id === productId ? { ...item, <span class="hljs-attr">quantity</span>: item.quantity + <span class="hljs-number">1</span> } : item
);
</code></pre>
<p><strong>Asynchronous JavaScript (Helpful)</strong></p>
<ul>
<li><p><strong>Promises and async/await</strong>: For understanding API calls in state management</p>
</li>
<li><p><strong>Basic error handling</strong>: try/catch blocks</p>
</li>
</ul>
<p><strong>Objects and Arrays (Required)</strong></p>
<ul>
<li><p>How to create, modify, and access nested objects and arrays</p>
</li>
<li><p>Understanding reference vs. value equality</p>
</li>
<li><p>Why direct mutation is problematic in React</p>
</li>
</ul>
<h3 id="heading-react-concepts-youll-encounter">React Concepts You'll Encounter</h3>
<p><strong>Component Hierarchy (Required)</strong></p>
<ul>
<li><p>How parent and child components relate</p>
</li>
<li><p>Data flow from parent to child</p>
</li>
<li><p>Why data can't easily flow "sideways" between sibling components</p>
</li>
</ul>
<p><strong>Re-rendering Behavior (Important)</strong></p>
<ul>
<li><p>When React components re-render</p>
</li>
<li><p>Why changing state causes re-renders</p>
</li>
<li><p>Basic understanding that creating new objects/functions causes re-renders</p>
</li>
</ul>
<p><strong>Event Handling (Required)</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// You should be comfortable with:</span>
&lt;button onClick={<span class="hljs-function">() =&gt;</span> handleClick(item.id)}&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setValue(e.target.value)} /&gt;</span>
</code></pre>
<h2 id="heading-development-environment">Development Environment</h2>
<p><strong>Tools You Should Have</strong></p>
<ul>
<li><p><strong>React DevTools</strong>: Browser extension for debugging React components</p>
</li>
<li><p><strong>Code editor</strong>: VS Code, WebStorm, or similar with React syntax highlighting</p>
</li>
<li><p><strong>Node.js and npm/yarn</strong>: For installing packages mentioned in examples</p>
</li>
</ul>
<p><strong>Helpful but Not Required</strong></p>
<ul>
<li><p><strong>TypeScript basics</strong>: Some examples mention TypeScript benefits</p>
</li>
<li><p><strong>Testing knowledge</strong>: The testing section assumes some familiarity with Jest/React Testing Library</p>
</li>
<li><p><strong>Build tools</strong>: Basic understanding of Create React App or Vite</p>
</li>
</ul>
<h2 id="heading-conceptual-understanding">Conceptual Understanding</h2>
<p><strong>Why State Management Matters</strong></p>
<p>You should have experienced or understand these pain points:</p>
<ul>
<li><p>Passing data through multiple component levels</p>
</li>
<li><p>Keeping data synchronized across different parts of your app</p>
</li>
<li><p>Managing complex application state</p>
</li>
</ul>
<p><strong>Basic Performance Awareness</strong></p>
<ul>
<li><p>Understanding that unnecessary re-renders can slow down apps</p>
</li>
<li><p>Awareness that some operations are more expensive than others</p>
</li>
</ul>
<h2 id="heading-what-you-dont-need-to-know">What You DON'T Need to Know</h2>
<p><strong>Advanced React Patterns</strong></p>
<ul>
<li><p>Higher-Order Components (HOCs)</p>
</li>
<li><p>Render props (though we explain them in the article)</p>
</li>
<li><p>Class components or lifecycle methods</p>
</li>
<li><p>Advanced hooks like <code>useLayoutEffect</code> or <code>useImperativeHandle</code></p>
</li>
</ul>
<p><strong>Complex State Management</strong></p>
<ul>
<li>You don't need prior experience with Redux, Context API, or other state libraries. I’ll explain everything from scratch</li>
</ul>
<p><strong>Advanced JavaScript</strong></p>
<ul>
<li><p>Closures, prototypes, or advanced functional programming concepts</p>
</li>
<li><p>Complex async patterns beyond basic promises</p>
</li>
</ul>
<h2 id="heading-self-assessment-questions">Self-Assessment Questions</h2>
<p>Before diving in, ask yourself:</p>
<ol>
<li><p><strong>Can I build a simple React app with multiple components?</strong></p>
</li>
<li><p><strong>Do I understand how to pass data from parent to child via props?</strong></p>
</li>
<li><p><strong>Can I handle form inputs with useState?</strong></p>
</li>
<li><p><strong>Do I know when a React component re-renders?</strong></p>
</li>
<li><p><strong>Am I comfortable with array methods like map() and filter()?</strong></p>
</li>
</ol>
<p>If you answered "yes" to most of these, you're ready for this handbook!</p>
<h2 id="heading-recommended-preparation">Recommended Preparation</h2>
<p><strong>If you need to brush up on React basics:</strong></p>
<ul>
<li><p>Complete the official React tutorial (tic-tac-toe game)</p>
</li>
<li><p>Build a simple todo app with local state</p>
</li>
<li><p>Practice passing props between components</p>
</li>
</ul>
<p><strong>If you need JavaScript review:</strong></p>
<ul>
<li><p>Practice array destructuring and spread syntax</p>
</li>
<li><p>Review arrow functions and array methods</p>
</li>
<li><p>Get comfortable with async/await</p>
</li>
</ul>
<p><strong>Quick warm-up exercise:</strong> Try building a simple counter app where:</p>
<ul>
<li><p>Parent component holds the count state</p>
</li>
<li><p>Multiple child components display or modify the count</p>
</li>
<li><p>You'll quickly see why prop drilling becomes a problem!</p>
</li>
</ul>
<h2 id="heading-what-this-guide-will-teach-you">What This Guide Will Teach You</h2>
<p>By the end, you'll understand:</p>
<ul>
<li><p>Why and when shared state becomes complex</p>
</li>
<li><p>How to solve prop drilling with Context API</p>
</li>
<li><p>When to use Redux, Zustand, or other state libraries</p>
</li>
<li><p>How to optimize performance with shared state</p>
</li>
<li><p>Testing strategies for state management</p>
</li>
<li><p>Best practices for maintainable code</p>
</li>
</ul>
<p>The guide is designed to take you from "I know basic React" to "I can architect state management for complex applications" with plenty of examples and explanations along the way.</p>
<h2 id="heading-understanding-the-building-blocks-props-in-react">Understanding the Building Blocks: Props in React</h2>
<p>Before we get into complex state management, let's understand the fundamentals.</p>
<h3 id="heading-what-are-props">What are props?</h3>
<p><strong>Props</strong> (short for "properties") are how React components communicate with each other. Think of props like passing notes between classrooms in a school – they carry information from one component to another.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// This is a simple component that displays a person's information</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PersonCard</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-comment">// props is an object containing all the data passed to this component</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"person-card"</span>&gt;</span>
      {/* We access the data using props.propertyName */}
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>           {/* Shows the person's name */}
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {props.age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>         {/* Shows the person's age */}
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Job: {props.job}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>         {/* Shows the person's job */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// This is how we USE the PersonCard component and pass it props</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* 
        We're creating a PersonCard component and passing it three props:
        - name: "Sarah"
        - age: 28  
        - job: "Developer"
      */}
      <span class="hljs-tag">&lt;<span class="hljs-name">PersonCard</span> 
        <span class="hljs-attr">name</span>=<span class="hljs-string">"Sarah"</span> 
        <span class="hljs-attr">age</span>=<span class="hljs-string">{28}</span> 
        <span class="hljs-attr">job</span>=<span class="hljs-string">"Developer"</span> 
      /&gt;</span>

      {/* We can create another PersonCard with different props */}
      <span class="hljs-tag">&lt;<span class="hljs-name">PersonCard</span> 
        <span class="hljs-attr">name</span>=<span class="hljs-string">"Mike"</span> 
        <span class="hljs-attr">age</span>=<span class="hljs-string">{35}</span> 
        <span class="hljs-attr">job</span>=<span class="hljs-string">"Designer"</span> 
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Let's break down what's happening:</strong></p>
<ol>
<li><p><strong>PersonCard</strong> is a function that receives <code>props</code> as its parameter</p>
</li>
<li><p><code>props</code> is a JavaScript object containing all the data we passed: <code>{name: "Sarah", age: 28, job: "Developer"}</code></p>
</li>
<li><p>We access individual pieces of data using dot notation: <code>props.name</code>, <code>props.age</code>, <code>props.job</code></p>
</li>
<li><p>The curly braces <code>{}</code> tell React "this is JavaScript code, not regular text"</p>
</li>
<li><p>When we use <code>&lt;PersonCard name="Sarah" age={28} job="Developer" /&gt;</code>, React automatically creates the props object</p>
</li>
</ol>
<h3 id="heading-a-more-modern-way-destructuring-props">A more modern way: Destructuring props</h3>
<p>Instead of writing <code>props.name</code> every time, we can use <strong>destructuring</strong> to extract the values directly:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Instead of this:</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PersonCard</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"person-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {props.age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Job: {props.job}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// We can write this (destructuring the props object):</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PersonCard</span>(<span class="hljs-params">{ name, age, job }</span>) </span>{
  <span class="hljs-comment">// JavaScript destructuring extracts name, age, and job from the props object</span>
  <span class="hljs-comment">// It's like saying: "Take the props object and create separate variables"</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"person-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>        {/* No need for props.name anymore */}
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>      {/* Just use the variable directly */}
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Job: {job}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>What destructuring does:</strong></p>
<ul>
<li><p><code>{ name, age, job }</code> tells JavaScript: "Extract the <code>name</code>, <code>age</code>, and <code>job</code> properties from the props object"</p>
</li>
<li><p>It creates separate variables with those names</p>
</li>
<li><p>This makes our code cleaner and easier to read</p>
</li>
</ul>
<h2 id="heading-what-is-prop-drilling-and-why-is-it-a-problem">What is Prop Drilling and Why is it a Problem?</h2>
<p><strong>Prop drilling</strong> happens when you need to pass data through multiple layers of components, even when the middle components don't use that data. It's like playing telephone through several people who don't care about the message.</p>
<h3 id="heading-a-simple-example-passing-a-username">A simple example: Passing a username</h3>
<pre><code class="lang-javascript"><span class="hljs-comment">// Let's say we want to show a user's name in a deeply nested component</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> userName = <span class="hljs-string">"Alice"</span>;  <span class="hljs-comment">// This data starts here at the top</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My Shopping App<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {/* We pass userName down to Header */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">userName</span>=<span class="hljs-string">{userName}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ userName }</span>) </span>{
  <span class="hljs-comment">// Header receives userName but doesn't actually display it</span>
  <span class="hljs-comment">// It just passes it down to Navigation</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"logo"</span>&gt;</span>ShopSmart<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {/* Header passes userName to Navigation */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Navigation</span> <span class="hljs-attr">userName</span>=<span class="hljs-string">{userName}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Navigation</span>(<span class="hljs-params">{ userName }</span>) </span>{
  <span class="hljs-comment">// Navigation also doesn't display userName</span>
  <span class="hljs-comment">// It just passes it down to UserMenu</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/products"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      {/* Navigation passes userName to UserMenu */}
      <span class="hljs-tag">&lt;<span class="hljs-name">UserMenu</span> <span class="hljs-attr">userName</span>=<span class="hljs-string">{userName}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserMenu</span>(<span class="hljs-params">{ userName }</span>) </span>{
  <span class="hljs-comment">// Finally! This component actually USES the userName</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-menu"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Welcome, {userName}!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>    {/* userName is displayed here */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>What's the problem here?</strong></p>
<ol>
<li><p><strong>Unnecessary complexity</strong>: <code>Header</code> and <code>Navigation</code> don't care about <code>userName</code>, but they have to know about it</p>
</li>
<li><p><strong>Tight coupling</strong>: If we want to change how <code>userName</code> works, we need to update multiple components</p>
</li>
<li><p><strong>Maintenance burden</strong>: Adding a new piece of user data means updating four different components</p>
</li>
<li><p><strong>Confusing code</strong>: It's hard to track where data is actually being used</p>
</li>
</ol>
<p>This is a simple example with just one piece of data. Imagine this with 5-10 different pieces of data!</p>
<h3 id="heading-a-realistic-example-shopping-cart-prop-drilling">A realistic example: Shopping cart prop drilling</h3>
<p>Now let's see how this becomes a real nightmare with a shopping cart:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The main App component - this is where our cart data lives</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// useState is a React hook that creates state (data that can change)</span>
  <span class="hljs-comment">// It returns an array with two items:</span>
  <span class="hljs-comment">// 1. The current value (cartItems)</span>
  <span class="hljs-comment">// 2. A function to update the value (setCartItems)</span>
  <span class="hljs-keyword">const</span> [cartItems, setCartItems] = useState([]);  <span class="hljs-comment">// Start with an empty array</span>

  <span class="hljs-comment">// Another piece of state for the total price</span>
  <span class="hljs-keyword">const</span> [cartTotal, setCartTotal] = useState(<span class="hljs-number">0</span>);   <span class="hljs-comment">// Start with 0</span>

  <span class="hljs-comment">// A function that adds items to the cart</span>
  <span class="hljs-keyword">const</span> addToCart = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    <span class="hljs-comment">// The spread operator (...) creates a new array with all existing items plus the new one</span>
    <span class="hljs-keyword">const</span> newCartItems = [...cartItems, product];
    setCartItems(newCartItems);                    <span class="hljs-comment">// Update the cart items</span>
    setCartTotal(cartTotal + product.price);       <span class="hljs-comment">// Update the total</span>
  };

  <span class="hljs-comment">// A function that removes items from the cart</span>
  <span class="hljs-keyword">const</span> removeFromCart = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    <span class="hljs-comment">// filter() creates a new array with only items that don't match the ID</span>
    <span class="hljs-keyword">const</span> updatedItems = cartItems.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);

    <span class="hljs-comment">// find() locates the item we're removing so we can subtract its price</span>
    <span class="hljs-keyword">const</span> removedItem = cartItems.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

    setCartItems(updatedItems);                           <span class="hljs-comment">// Update items</span>
    setCartTotal(cartTotal - removedItem.price);          <span class="hljs-comment">// Update total</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app"</span>&gt;</span>
      {/* 
        We need to pass cart data to Header so it can show the cart count
        Look how many props we need to pass!
      */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> 
        <span class="hljs-attr">cartItems</span>=<span class="hljs-string">{cartItems}</span>         // <span class="hljs-attr">Pass</span> <span class="hljs-attr">the</span> <span class="hljs-attr">entire</span> <span class="hljs-attr">cart</span> <span class="hljs-attr">array</span>
        <span class="hljs-attr">cartTotal</span>=<span class="hljs-string">{cartTotal}</span>         // <span class="hljs-attr">Pass</span> <span class="hljs-attr">the</span> <span class="hljs-attr">total</span> <span class="hljs-attr">price</span>
        <span class="hljs-attr">addToCart</span>=<span class="hljs-string">{addToCart}</span>         // <span class="hljs-attr">Pass</span> <span class="hljs-attr">the</span> <span class="hljs-attr">add</span> <span class="hljs-attr">function</span>
        <span class="hljs-attr">removeFromCart</span>=<span class="hljs-string">{removeFromCart}</span> // <span class="hljs-attr">Pass</span> <span class="hljs-attr">the</span> <span class="hljs-attr">remove</span> <span class="hljs-attr">function</span>
      /&gt;</span>

      {/* MainContent also needs all the cart functionality */}
      <span class="hljs-tag">&lt;<span class="hljs-name">MainContent</span> 
        <span class="hljs-attr">cartItems</span>=<span class="hljs-string">{cartItems}</span>
        <span class="hljs-attr">cartTotal</span>=<span class="hljs-string">{cartTotal}</span>
        <span class="hljs-attr">addToCart</span>=<span class="hljs-string">{addToCart}</span>
        <span class="hljs-attr">removeFromCart</span>=<span class="hljs-string">{removeFromCart}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now let's see what happens in the Header component:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ cartItems, cartTotal, addToCart, removeFromCart }</span>) </span>{
  <span class="hljs-comment">// Header receives all these props but only uses some of them</span>
  <span class="hljs-comment">// It needs to pass them down to other components</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"logo"</span>&gt;</span>ShopSmart<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      {/* 
        Navigation needs to show cart count, so we pass cartItems
        But it doesn't need addToCart or removeFromCart
        However, we might pass them "just in case"
      */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Navigation</span> 
        <span class="hljs-attr">cartItems</span>=<span class="hljs-string">{cartItems}</span>
        <span class="hljs-attr">cartTotal</span>=<span class="hljs-string">{cartTotal}</span>
        <span class="hljs-attr">addToCart</span>=<span class="hljs-string">{addToCart}</span>           // <span class="hljs-attr">Navigation</span> <span class="hljs-attr">doesn</span>'<span class="hljs-attr">t</span> <span class="hljs-attr">use</span> <span class="hljs-attr">this</span>
        <span class="hljs-attr">removeFromCart</span>=<span class="hljs-string">{removeFromCart}</span>  // <span class="hljs-attr">Navigation</span> <span class="hljs-attr">doesn</span>'<span class="hljs-attr">t</span> <span class="hljs-attr">use</span> <span class="hljs-attr">this</span> <span class="hljs-attr">either</span>
      /&gt;</span>

      {/* UserMenu might want to show cart total */}
      <span class="hljs-tag">&lt;<span class="hljs-name">UserMenu</span> 
        <span class="hljs-attr">cartTotal</span>=<span class="hljs-string">{cartTotal}</span>
        <span class="hljs-attr">addToCart</span>=<span class="hljs-string">{addToCart}</span>           // <span class="hljs-attr">UserMenu</span> <span class="hljs-attr">doesn</span>'<span class="hljs-attr">t</span> <span class="hljs-attr">use</span> <span class="hljs-attr">this</span>
        <span class="hljs-attr">removeFromCart</span>=<span class="hljs-string">{removeFromCart}</span>  // <span class="hljs-attr">UserMenu</span> <span class="hljs-attr">doesn</span>'<span class="hljs-attr">t</span> <span class="hljs-attr">use</span> <span class="hljs-attr">this</span> <span class="hljs-attr">either</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Navigation</span>(<span class="hljs-params">{ cartItems, cartTotal, addToCart, removeFromCart }</span>) </span>{
  <span class="hljs-comment">// Navigation only cares about showing the cart count</span>
  <span class="hljs-comment">// But it receives ALL the cart props anyway</span>

  <span class="hljs-keyword">const</span> itemCount = cartItems.length;  <span class="hljs-comment">// Calculate how many items in cart</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/products"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>

      {/* This is the ONLY place Navigation actually uses the cart data */}
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/cart"</span>&gt;</span>
        Cart 
        {/* Only show the badge if there are items */}
        {itemCount &gt; 0 &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>{itemCount}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>The problems are multiplying:</strong></p>
<ol>
<li><p><strong>Props pollution</strong>: Components receive props they don't use</p>
</li>
<li><p><strong>Confusing interfaces</strong>: It's hard to tell what each component actually needs</p>
</li>
<li><p><strong>Change ripple effects</strong>: Modifying cart functionality might require changing 6+ components</p>
</li>
<li><p><strong>Testing complexity</strong>: Testing Navigation requires mocking cart functions it doesn't even use</p>
</li>
<li><p><strong>Performance issues</strong>: Changing cart data causes ALL components in the chain to re-render</p>
</li>
</ol>
<h3 id="heading-why-does-this-happen-and-get-worse">Why does this happen and get worse</h3>
<p>This pattern emerges naturally because:</p>
<ol>
<li><p><strong>React is one-way data flow</strong>: Data can only flow down from parent to child</p>
</li>
<li><p><strong>Component hierarchy</strong>: Your UI structure determines your data flow</p>
</li>
<li><p><strong>No built-in sharing mechanism</strong>: React doesn't provide a way for distant components to share data directly</p>
</li>
</ol>
<p>As your app grows, you end up with:</p>
<ul>
<li><p>10+ props being passed through 5+ levels</p>
</li>
<li><p>Components that exist just to pass props along</p>
</li>
<li><p>Developers afraid to refactor because they might break the prop chain</p>
</li>
<li><p>New features requiring changes to unrelated components</p>
</li>
</ul>
<h2 id="heading-solution-1-react-context-api-understanding-the-concept">Solution 1: React Context API – Understanding the Concept</h2>
<p>The <strong>Context API</strong> is React's built-in solution for sharing data between components without prop drilling. Think of it like a radio station that broadcasts information, and any component can tune in to listen.</p>
<h3 id="heading-the-radio-station-analogy">The radio station analogy</h3>
<p><strong>Traditional prop drilling</strong> is like passing a note through a chain of people:</p>
<ul>
<li><p>Person A tells Person B</p>
</li>
<li><p>Person B tells Person C</p>
</li>
<li><p>Person C tells Person D</p>
</li>
<li><p>Only Person D actually needs the information</p>
</li>
</ul>
<p><strong>React Context</strong> is like a radio broadcast:</p>
<ul>
<li><p>The radio station broadcasts information</p>
</li>
<li><p>Anyone with a radio can listen directly</p>
</li>
<li><p>No need to pass messages through intermediaries</p>
</li>
</ul>
<h3 id="heading-what-is-createcontext">What is <code>createContext()</code>?</h3>
<p><code>createContext()</code> is a React function that creates a "broadcasting system" for your data. It returns two things:</p>
<ol>
<li><p><strong>Provider</strong>: The "radio station" that broadcasts data</p>
</li>
<li><p><strong>Consumer</strong>: The "radio" that components use to listen for data</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// createContext() creates our "radio station"</span>
<span class="hljs-comment">// We can pass a default value (like a default radio frequency)</span>
<span class="hljs-keyword">const</span> CartContext = createContext();

<span class="hljs-comment">// CartContext now contains:</span>
<span class="hljs-comment">// - CartContext.Provider (the broadcaster)</span>
<span class="hljs-comment">// - CartContext.Consumer (the listener, though we rarely use this directly)</span>
</code></pre>
<p><strong>What createContext() actually does:</strong></p>
<ul>
<li><p>Creates a special React object that can share data</p>
</li>
<li><p>The default value is used when a component tries to access the context but isn't inside a Provider</p>
</li>
<li><p>Returns an object with Provider and Consumer components</p>
</li>
</ul>
<h3 id="heading-creating-a-basic-context-provider">Creating a basic Context Provider</h3>
<p>A <strong>Provider</strong> is a component that makes data available to all its children:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Step 1: Create the context</span>
<span class="hljs-keyword">const</span> CartContext = createContext();

<span class="hljs-comment">// Step 2: Create a Provider component</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-comment">// children is a special prop that contains whatever components are inside CartProvider</span>

  <span class="hljs-comment">// This is our cart state - same as before</span>
  <span class="hljs-keyword">const</span> [cartItems, setCartItems] = useState([]);
  <span class="hljs-keyword">const</span> [cartTotal, setCartTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-comment">// Our cart functions</span>
  <span class="hljs-keyword">const</span> addToCart = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> newCartItems = [...cartItems, product];
    setCartItems(newCartItems);
    setCartTotal(cartTotal + product.price);
  };

  <span class="hljs-keyword">const</span> removeFromCart = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> updatedItems = cartItems.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);
    <span class="hljs-keyword">const</span> removedItem = cartItems.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

    setCartItems(updatedItems);
    <span class="hljs-keyword">if</span> (removedItem) {  <span class="hljs-comment">// Make sure we found the item before subtracting</span>
      setCartTotal(cartTotal - removedItem.price);
    }
  };

  <span class="hljs-comment">// This object contains everything we want to share</span>
  <span class="hljs-keyword">const</span> cartValue = {
    cartItems,      <span class="hljs-comment">// The array of items</span>
    cartTotal,      <span class="hljs-comment">// The total price</span>
    addToCart,      <span class="hljs-comment">// Function to add items</span>
    removeFromCart, <span class="hljs-comment">// Function to remove items</span>
    <span class="hljs-attr">itemCount</span>: cartItems.length  <span class="hljs-comment">// Calculated value for convenience</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">/* 
      CartContext.Provider is the "radio station"
      - value prop is what gets "broadcasted"
      - children are all the components that can "listen" to this broadcast
    */</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{cartValue}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Let's break down this Provider:</strong></p>
<ol>
<li><p><strong>Function component</strong>: <code>CartProvider</code> is just a regular React component</p>
</li>
<li><p><strong>children prop</strong>: This contains whatever JSX is placed inside <code>&lt;CartProvider&gt;...&lt;/CartProvider&gt;</code></p>
</li>
<li><p><strong>State management</strong>: We manage cart state exactly like before with <code>useState</code></p>
</li>
<li><p><strong>value prop</strong>: This is crucial – whatever we put here becomes available to all child components</p>
</li>
<li><p><strong>Return JSX</strong>: We wrap <code>children</code> in <code>CartContext.Provider</code> to "broadcast" our data</p>
</li>
</ol>
<h3 id="heading-understanding-the-usecontext-hook">Understanding the useContext hook</h3>
<p><strong>useContext</strong> is a React hook that lets components "tune in" to a Context broadcast:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// useContext(CartContext) "tunes in" to our cart data</span>
  <span class="hljs-comment">// It returns whatever we put in the value prop of CartProvider</span>
  <span class="hljs-keyword">const</span> cartData = useContext(CartContext);

  <span class="hljs-comment">// cartData now contains: { cartItems, cartTotal, addToCart, removeFromCart, itemCount }</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      {/* We can access any property from our cartValue object */}
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Cart ({cartData.itemCount})<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>What useContext() does:</strong></p>
<ol>
<li><p><strong>Looks up the component tree</strong>: Finds the nearest CartContext.Provider</p>
</li>
<li><p><strong>Returns the value</strong>: Gives us whatever was passed to the value prop</p>
</li>
<li><p><strong>Automatically re-renders</strong>: When the context value changes, this component updates</p>
</li>
<li><p><strong>Throws an error</strong>: If no Provider is found, it returns the default value (or undefined)</p>
</li>
</ol>
<h3 id="heading-creating-a-custom-hook-for-cleaner-usage">Creating a custom hook for cleaner usage</h3>
<p>Instead of using <code>useContext(CartContext)</code> everywhere, we can create a custom hook:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Custom hook that wraps useContext</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCart</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Get the cart data from context</span>
  <span class="hljs-keyword">const</span> context = useContext(CartContext);

  <span class="hljs-comment">// Check if we're inside a CartProvider</span>
  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useCart must be used within a CartProvider'</span>);
  }

  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-comment">// Now components can use our custom hook</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { itemCount } = useCart();  <span class="hljs-comment">// Much cleaner!</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Cart ({itemCount})<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>There are various reasons to create a custom hook:</p>
<ol>
<li><p><strong>Better error messages</strong>: We get a clear error if someone forgets the Provider</p>
</li>
<li><p><strong>Cleaner imports</strong>: Import <code>useCart</code> instead of <code>useContext</code> and <code>CartContext</code></p>
</li>
<li><p><strong>Future flexibility</strong>: We can add logic to the hook later if needed</p>
</li>
<li><p><strong>Type safety</strong>: In TypeScript, this provides better type inference</p>
</li>
</ol>
<h3 id="heading-putting-it-all-together-complete-context-example">Putting it all together: Complete Context example</h3>
<p>Now let's see how our shopping cart looks with Context instead of prop drilling:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createContext, useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Step 1: Create the context</span>
<span class="hljs-keyword">const</span> CartContext = createContext();

<span class="hljs-comment">// Step 2: Create custom hook</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCart</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> context = useContext(CartContext);
  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useCart must be used within a CartProvider'</span>);
  }
  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-comment">// Step 3: Create the Provider</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [cartItems, setCartItems] = useState([]);
  <span class="hljs-keyword">const</span> [cartTotal, setCartTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> addToCart = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> newCartItems = [...cartItems, product];
    setCartItems(newCartItems);
    setCartTotal(cartTotal + product.price);
  };

  <span class="hljs-keyword">const</span> removeFromCart = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> updatedItems = cartItems.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);
    <span class="hljs-keyword">const</span> removedItem = cartItems.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

    setCartItems(updatedItems);
    <span class="hljs-keyword">if</span> (removedItem) {
      setCartTotal(cartTotal - removedItem.price);
    }
  };

  <span class="hljs-keyword">const</span> value = {
    cartItems,
    cartTotal,
    addToCart,
    removeFromCart,
    <span class="hljs-attr">itemCount</span>: cartItems.length
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Step 4: Use the context in components</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">// Wrap our app in the CartProvider</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app"</span>&gt;</span>
        {/* No props needed! */}
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MainContent</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartProvider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Header doesn't need any cart props</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"logo"</span>&gt;</span>ShopSmart<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Navigation</span> /&gt;</span>  {/* No props passed here either */}
      <span class="hljs-tag">&lt;<span class="hljs-name">UserMenu</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Navigation</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Navigation gets cart data directly from context</span>
  <span class="hljs-keyword">const</span> { itemCount } = useCart();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/products"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/cart"</span>&gt;</span>
        Cart 
        {itemCount &gt; 0 &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>{itemCount}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductCard</span>(<span class="hljs-params">{ product }</span>) </span>{
  <span class="hljs-comment">// ProductCard gets the addToCart function directly</span>
  <span class="hljs-keyword">const</span> { addToCart } = useCart();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{product.description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"price"</span>&gt;</span>${product.price}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

      {/* No prop drilling needed! */}
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addToCart(product)}&gt;
        Add to Cart
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartSidebar</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// CartSidebar gets cart items and remove function directly</span>
  <span class="hljs-keyword">const</span> { cartItems, removeFromCart } = useCart();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-sidebar"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Your Cart<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      {cartItems.length === 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Your cart is empty<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
          {cartItems.map(item =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name} - ${item.price}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeFromCart(item.id)}&gt;
                Remove
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Export our Provider and hook for use in other files</span>
<span class="hljs-keyword">export</span> { CartProvider, useCart };
</code></pre>
<p><strong>Compare this to our prop drilling version:</strong></p>
<p><strong>Before (Prop Drilling):</strong></p>
<ul>
<li><p>App passes 4 props to Header</p>
</li>
<li><p>Header passes 4 props to Navigation (even though Navigation only needs 1)</p>
</li>
<li><p>Navigation receives props it doesn't use</p>
</li>
<li><p>Every component in the chain needs to know about cart structure</p>
</li>
</ul>
<p><strong>After (Context):</strong></p>
<ul>
<li><p>App only needs to wrap components in CartProvider</p>
</li>
<li><p>Header doesn't handle any cart props</p>
</li>
<li><p>Navigation directly gets only what it needs (<code>itemCount</code>)</p>
</li>
<li><p>ProductCard directly gets only what it needs (<code>addToCart</code>)</p>
</li>
<li><p>Each component is independent and focused</p>
</li>
</ul>
<h2 id="heading-advanced-context-patterns-and-concepts">Advanced Context Patterns and Concepts</h2>
<p>Now that you understand the basics, let's explore more sophisticated Context patterns that you'll encounter in real applications.</p>
<h3 id="heading-multiple-contexts-for-separation-of-concerns">Multiple contexts for separation of concerns</h3>
<p>In real applications, you don't want to put everything in one giant context. Instead, you can create separate contexts for different domains:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Separate contexts for different types of data</span>
<span class="hljs-keyword">const</span> UserContext = createContext();     <span class="hljs-comment">// User authentication and profile</span>
<span class="hljs-keyword">const</span> ThemeContext = createContext();    <span class="hljs-comment">// UI theme and appearance  </span>
<span class="hljs-keyword">const</span> CartContext = createContext();     <span class="hljs-comment">// Shopping cart functionality</span>

<span class="hljs-comment">// User Provider - handles authentication</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);           <span class="hljs-comment">// Current user data</span>
  <span class="hljs-keyword">const</span> [isLoggedIn, setIsLoggedIn] = useState(<span class="hljs-literal">false</span>); <span class="hljs-comment">// Login status</span>

  <span class="hljs-comment">// Function to log in a user</span>
  <span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> (email, password) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// authAPI would be your authentication service (like Firebase, Auth0, etc.)</span>
      <span class="hljs-keyword">const</span> userData = <span class="hljs-keyword">await</span> authAPI.login(email, password);
      setUser(userData);        <span class="hljs-comment">// Store user information</span>
      setIsLoggedIn(<span class="hljs-literal">true</span>);      <span class="hljs-comment">// Mark as logged in</span>
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Login failed:'</span>, error);
      <span class="hljs-comment">// Handle login errors (show message to user, etc.)</span>
    }
  };

  <span class="hljs-comment">// Function to log out a user</span>
  <span class="hljs-keyword">const</span> logout = <span class="hljs-function">() =&gt;</span> {
    setUser(<span class="hljs-literal">null</span>);            <span class="hljs-comment">// Clear user data</span>
    setIsLoggedIn(<span class="hljs-literal">false</span>);     <span class="hljs-comment">// Mark as logged out</span>
    <span class="hljs-comment">// You might also clear localStorage, redirect to login page, etc.</span>
  };

  <span class="hljs-keyword">const</span> value = {
    user,         <span class="hljs-comment">// Current user object: { id, name, email, etc. }</span>
    isLoggedIn,   <span class="hljs-comment">// Boolean: true if user is logged in</span>
    login,        <span class="hljs-comment">// Function to log in</span>
    logout,       <span class="hljs-comment">// Function to log out</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Theme Provider - handles UI appearance</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);      <span class="hljs-comment">// 'light' or 'dark'</span>
  <span class="hljs-keyword">const</span> [fontSize, setFontSize] = useState(<span class="hljs-string">'medium'</span>); <span class="hljs-comment">// 'small', 'medium', 'large'</span>

  <span class="hljs-comment">// Function to switch between light and dark themes</span>
  <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> {
    setTheme(<span class="hljs-function"><span class="hljs-params">currentTheme</span> =&gt;</span> currentTheme === <span class="hljs-string">'light'</span> ? <span class="hljs-string">'dark'</span> : <span class="hljs-string">'light'</span>);
  };

  <span class="hljs-comment">// Function to update font size</span>
  <span class="hljs-keyword">const</span> updateFontSize = <span class="hljs-function">(<span class="hljs-params">size</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> ([<span class="hljs-string">'small'</span>, <span class="hljs-string">'medium'</span>, <span class="hljs-string">'large'</span>].includes(size)) {
      setFontSize(size);
    }
  };

  <span class="hljs-keyword">const</span> value = {
    theme,          <span class="hljs-comment">// Current theme: 'light' or 'dark'</span>
    fontSize,       <span class="hljs-comment">// Current font size: 'small', 'medium', or 'large'</span>
    toggleTheme,    <span class="hljs-comment">// Function to switch themes</span>
    updateFontSize, <span class="hljs-comment">// Function to change font size</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Custom hooks for each context</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> context = useContext(UserContext);
  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useUser must be used within a UserProvider'</span>);
  }
  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useTheme</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> context = useContext(ThemeContext);
  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useTheme must be used within a ThemeProvider'</span>);
  }
  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-comment">// App with multiple providers</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">// You can nest providers in any order</span>
    <span class="hljs-comment">// Each provider makes its data available to all children</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">CartProvider</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">MainContent</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">CartProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserProvider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Component using multiple contexts</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProfile</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { user, logout } = useUser();           <span class="hljs-comment">// Get user data</span>
  <span class="hljs-keyword">const</span> { theme, toggleTheme } = useTheme();    <span class="hljs-comment">// Get theme data</span>
  <span class="hljs-keyword">const</span> { itemCount } = useCart();              <span class="hljs-comment">// Get cart data</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">user-profile</span> <span class="hljs-attr">theme-</span>${<span class="hljs-attr">theme</span>}`}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Welcome, {user?.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Items in cart: {itemCount}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggleTheme}</span>&gt;</span>
        Switch to {theme === 'light' ? 'dark' : 'light'} theme
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{logout}</span>&gt;</span>
        Logout
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>So why should you use separate contexts? First, performance considerations: components only re-render when the specific context they use changes. Second, it’s helpful for organizational purposes as related functionality is grouped together. It’s also great for reusability, as you can use UserProvider in different apps without cart functionality. And finally, it’s easier to test components that only depend on specific contexts.</p>
<h3 id="heading-understanding-usereducer-for-complex-state-logic">Understanding <code>useReducer</code> for complex state logic</h3>
<p>When your context state becomes complex with multiple related values and complex update logic, <code>useReducer</code> is often a better choice than multiple <code>useState</code> calls.</p>
<p><strong>What is useReducer?</strong> <code>useReducer</code> is a React hook that manages state through a "reducer" function. Instead of directly setting state, you "dispatch actions" that describe what happened, and the reducer decides how to update the state.</p>
<p>Think of it like a vending machine:</p>
<ul>
<li><p>You press buttons (dispatch actions) to describe what you want</p>
</li>
<li><p>The machine has internal logic (reducer) that determines what happens</p>
</li>
<li><p>The machine gives you the result (new state)</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// First, let's define what actions our cart can handle</span>
<span class="hljs-keyword">const</span> cartActions = {
  <span class="hljs-attr">ADD_ITEM</span>: <span class="hljs-string">'ADD_ITEM'</span>,           <span class="hljs-comment">// Add a product to cart</span>
  <span class="hljs-attr">REMOVE_ITEM</span>: <span class="hljs-string">'REMOVE_ITEM'</span>,     <span class="hljs-comment">// Remove a product completely</span>
  <span class="hljs-attr">UPDATE_QUANTITY</span>: <span class="hljs-string">'UPDATE_QUANTITY'</span>, <span class="hljs-comment">// Change quantity of existing item</span>
  <span class="hljs-attr">CLEAR_CART</span>: <span class="hljs-string">'CLEAR_CART'</span>,       <span class="hljs-comment">// Empty the entire cart</span>
  <span class="hljs-attr">APPLY_DISCOUNT</span>: <span class="hljs-string">'APPLY_DISCOUNT'</span> <span class="hljs-comment">// Apply a discount code</span>
};

<span class="hljs-comment">// The reducer function: decides how state changes based on actions</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cartReducer</span>(<span class="hljs-params">state, action</span>) </span>{
  <span class="hljs-comment">// state: current cart state</span>
  <span class="hljs-comment">// action: object describing what happened, like { type: 'ADD_ITEM', payload: product }</span>

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> cartActions.ADD_ITEM: {
      <span class="hljs-keyword">const</span> product = action.payload;  <span class="hljs-comment">// The product being added</span>

      <span class="hljs-comment">// Check if this product is already in the cart</span>
      <span class="hljs-keyword">const</span> existingItemIndex = state.items.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === product.id);

      <span class="hljs-keyword">if</span> (existingItemIndex &gt;= <span class="hljs-number">0</span>) {
        <span class="hljs-comment">// Product exists: increase its quantity</span>
        <span class="hljs-keyword">const</span> updatedItems = [...state.items];  <span class="hljs-comment">// Create a copy of items array</span>
        updatedItems[existingItemIndex] = {
          ...updatedItems[existingItemIndex],    <span class="hljs-comment">// Copy existing item properties</span>
          <span class="hljs-attr">quantity</span>: updatedItems[existingItemIndex].quantity + <span class="hljs-number">1</span>  <span class="hljs-comment">// Increase quantity</span>
        };

        <span class="hljs-keyword">return</span> {
          ...state,                              <span class="hljs-comment">// Keep other state properties</span>
          <span class="hljs-attr">items</span>: updatedItems,                   <span class="hljs-comment">// Update items array</span>
          <span class="hljs-attr">total</span>: state.total + product.price,   <span class="hljs-comment">// Add to total</span>
          <span class="hljs-attr">itemCount</span>: state.itemCount + <span class="hljs-number">1</span>,       <span class="hljs-comment">// Increase count</span>
        };
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// New product: add it to cart</span>
        <span class="hljs-keyword">const</span> newItem = { 
          ...product,     <span class="hljs-comment">// Copy all product properties (id, name, price, and so on)</span>
          <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span>     <span class="hljs-comment">// Add quantity property</span>
        };

        <span class="hljs-keyword">return</span> {
          ...state,                                    <span class="hljs-comment">// Keep other state properties</span>
          <span class="hljs-attr">items</span>: [...state.items, newItem],           <span class="hljs-comment">// Add new item to array</span>
          <span class="hljs-attr">total</span>: state.total + product.price,         <span class="hljs-comment">// Add to total</span>
          <span class="hljs-attr">itemCount</span>: state.itemCount + <span class="hljs-number">1</span>,             <span class="hljs-comment">// Increase count</span>
        };
      }
    }

    <span class="hljs-keyword">case</span> cartActions.REMOVE_ITEM: {
      <span class="hljs-keyword">const</span> productId = action.payload;  <span class="hljs-comment">// ID of product to remove</span>

      <span class="hljs-comment">// Find the item being removed</span>
      <span class="hljs-keyword">const</span> itemToRemove = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-comment">// If item doesn't exist, return state unchanged</span>
      <span class="hljs-keyword">if</span> (!itemToRemove) <span class="hljs-keyword">return</span> state;

      <span class="hljs-comment">// Remove the item from the array</span>
      <span class="hljs-keyword">const</span> updatedItems = state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);

      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">items</span>: updatedItems,
        <span class="hljs-comment">// Subtract the total price of removed item (price × quantity)</span>
        <span class="hljs-attr">total</span>: state.total - (itemToRemove.price * itemToRemove.quantity),
        <span class="hljs-comment">// Subtract the quantity of removed item</span>
        <span class="hljs-attr">itemCount</span>: state.itemCount - itemToRemove.quantity,
      };
    }

    <span class="hljs-keyword">case</span> cartActions.UPDATE_QUANTITY: {
      <span class="hljs-keyword">const</span> { productId, quantity } = action.payload;

      <span class="hljs-comment">// If quantity is 0 or less, remove the item</span>
      <span class="hljs-keyword">if</span> (quantity &lt;= <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> cartReducer(state, {
          <span class="hljs-attr">type</span>: cartActions.REMOVE_ITEM,
          <span class="hljs-attr">payload</span>: productId
        });
      }

      <span class="hljs-keyword">const</span> updatedItems = state.items.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (item.id === productId) {
          <span class="hljs-keyword">return</span> { ...item, quantity };  <span class="hljs-comment">// Update this item's quantity</span>
        }
        <span class="hljs-keyword">return</span> item;  <span class="hljs-comment">// Keep other items unchanged</span>
      });

      <span class="hljs-comment">// Find the item to calculate price difference</span>
      <span class="hljs-keyword">const</span> item = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);
      <span class="hljs-keyword">if</span> (!item) <span class="hljs-keyword">return</span> state;  <span class="hljs-comment">// Item not found, no change</span>

      <span class="hljs-keyword">const</span> quantityDifference = quantity - item.quantity;

      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">items</span>: updatedItems,
        <span class="hljs-attr">total</span>: state.total + (item.price * quantityDifference),
        <span class="hljs-attr">itemCount</span>: state.itemCount + quantityDifference,
      };
    }

    <span class="hljs-keyword">case</span> cartActions.CLEAR_CART: {
      <span class="hljs-comment">// Reset everything to initial state</span>
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">items</span>: [],
        <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">discount</span>: <span class="hljs-number">0</span>,
      };
    }

    <span class="hljs-keyword">case</span> cartActions.APPLY_DISCOUNT: {
      <span class="hljs-keyword">const</span> discountPercent = action.payload;  <span class="hljs-comment">// Discount percentage (for example, 10 for 10%)</span>
      <span class="hljs-keyword">const</span> discountAmount = state.total * (discountPercent / <span class="hljs-number">100</span>);

      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">discount</span>: discountAmount,
      };
    }

    <span class="hljs-attr">default</span>:
      <span class="hljs-comment">// If we don't recognize the action type, return state unchanged</span>
      <span class="hljs-keyword">return</span> state;
  }
}

<span class="hljs-comment">// Updated CartProvider using useReducer</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-comment">// Initial state for our cart</span>
  <span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">items</span>: [],       <span class="hljs-comment">// Array of cart items</span>
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,        <span class="hljs-comment">// Total price before discount</span>
    <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>,    <span class="hljs-comment">// Total number of items</span>
    <span class="hljs-attr">discount</span>: <span class="hljs-number">0</span>,     <span class="hljs-comment">// Discount amount</span>
  };

  <span class="hljs-comment">// useReducer takes two arguments:</span>
  <span class="hljs-comment">// 1. The reducer function (cartReducer)</span>
  <span class="hljs-comment">// 2. The initial state</span>
  <span class="hljs-comment">// It returns:</span>
  <span class="hljs-comment">// 1. Current state</span>
  <span class="hljs-comment">// 2. Dispatch function to send actions</span>
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(cartReducer, initialState);

  <span class="hljs-comment">// Action creator functions - these create action objects</span>
  <span class="hljs-keyword">const</span> addItem = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: cartActions.ADD_ITEM,    <span class="hljs-comment">// What happened</span>
      <span class="hljs-attr">payload</span>: product               <span class="hljs-comment">// The data needed</span>
    });
  };

  <span class="hljs-keyword">const</span> removeItem = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: cartActions.REMOVE_ITEM,
      <span class="hljs-attr">payload</span>: productId
    });
  };

  <span class="hljs-keyword">const</span> updateQuantity = <span class="hljs-function">(<span class="hljs-params">productId, quantity</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: cartActions.UPDATE_QUANTITY,
      <span class="hljs-attr">payload</span>: { productId, quantity }
    });
  };

  <span class="hljs-keyword">const</span> clearCart = <span class="hljs-function">() =&gt;</span> {
    dispatch({ <span class="hljs-attr">type</span>: cartActions.CLEAR_CART });
  };

  <span class="hljs-keyword">const</span> applyDiscount = <span class="hljs-function">(<span class="hljs-params">discountPercent</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: cartActions.APPLY_DISCOUNT,
      <span class="hljs-attr">payload</span>: discountPercent
    });
  };

  <span class="hljs-comment">// Calculate final total (total minus discount)</span>
  <span class="hljs-keyword">const</span> finalTotal = state.total - state.discount;

  <span class="hljs-keyword">const</span> value = {
    <span class="hljs-comment">// State values</span>
    <span class="hljs-attr">items</span>: state.items,
    <span class="hljs-attr">total</span>: state.total,
    <span class="hljs-attr">itemCount</span>: state.itemCount,
    <span class="hljs-attr">discount</span>: state.discount,
    finalTotal,

    <span class="hljs-comment">// Action functions</span>
    addItem,
    removeItem,
    updateQuantity,
    clearCart,
    applyDiscount,
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p><code>useReducer</code> has various benefits over multiple <code>useState</code>s:</p>
<ol>
<li><p><strong>Centralized logic</strong>: All cart update logic is in one place (the reducer)</p>
</li>
<li><p><strong>Predictable updates</strong>: Actions describe what happened, reducer decides how to update</p>
</li>
<li><p><strong>Easier testing</strong>: You can test the reducer function independently</p>
</li>
<li><p><strong>Better for complex state</strong>: When state has multiple related values that change together</p>
</li>
<li><p><strong>Debugging</strong>: You can log all actions to see exactly what happened</p>
</li>
</ol>
<h2 id="heading-solution-2-state-management-libraries-explained">Solution 2: State Management Libraries Explained</h2>
<p>While React Context is great for medium-complexity applications, larger applications often benefit from dedicated state management libraries. Let's explore the most popular options.</p>
<h3 id="heading-understanding-redux-the-predictable-state-container">Understanding Redux: The predictable state container</h3>
<p><strong>Redux</strong> is a library that provides a single, centralized store for all your application state. Think of it like a giant database that your entire app shares, with strict rules about how data can be changed.</p>
<h4 id="heading-core-redux-concepts">Core Redux concepts</h4>
<p><strong>1. Store</strong>: The single source of truth for your app's state</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The store is like a database that holds ALL your app's state</span>
<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-comment">// Example of what your entire app state might look like</span>
<span class="hljs-keyword">const</span> initialAppState = {
  <span class="hljs-attr">user</span>: {
    <span class="hljs-attr">id</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">isLoggedIn</span>: <span class="hljs-literal">false</span>
  },
  <span class="hljs-attr">cart</span>: {
    <span class="hljs-attr">items</span>: [],
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">discount</span>: <span class="hljs-number">0</span>
  },
  <span class="hljs-attr">ui</span>: {
    <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>,
    <span class="hljs-attr">sidebarOpen</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>
  }
};

<span class="hljs-comment">// The store holds this state and provides methods to interact with it</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer, initialAppState);

<span class="hljs-comment">// You can get the current state at any time</span>
<span class="hljs-keyword">const</span> currentState = store.getState();
<span class="hljs-built_in">console</span>.log(currentState.cart.items);  <span class="hljs-comment">// Access cart items</span>
<span class="hljs-built_in">console</span>.log(currentState.user.name);   <span class="hljs-comment">// Access user name</span>
</code></pre>
<p><strong>2. Actions</strong>: Plain objects that describe what happened</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Actions are like event descriptions - they tell Redux what happened</span>
<span class="hljs-comment">// They must have a 'type' property and optionally a 'payload'</span>

<span class="hljs-comment">// Action to add item to cart</span>
<span class="hljs-keyword">const</span> addItemAction = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'cart/addItem'</span>,              <span class="hljs-comment">// Describes what happened</span>
  <span class="hljs-attr">payload</span>: {                        <span class="hljs-comment">// The data needed</span>
    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">'T-Shirt'</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-number">25</span>
  }
};

<span class="hljs-comment">// Action to log in user</span>
<span class="hljs-keyword">const</span> loginAction = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'user/login'</span>,
  <span class="hljs-attr">payload</span>: {
    <span class="hljs-attr">id</span>: <span class="hljs-number">123</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">'alice@example.com'</span>
  }
};

<span class="hljs-comment">// Action to toggle theme</span>
<span class="hljs-keyword">const</span> toggleThemeAction = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'ui/toggleTheme'</span>            <span class="hljs-comment">// No payload needed</span>
};

<span class="hljs-comment">// Action creators: functions that create actions</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addItem</span>(<span class="hljs-params">product</span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">'cart/addItem'</span>,
    <span class="hljs-attr">payload</span>: product
  };
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">loginUser</span>(<span class="hljs-params">userData</span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">'user/login'</span>,
    <span class="hljs-attr">payload</span>: userData
  };
}

<span class="hljs-comment">// Usage</span>
<span class="hljs-keyword">const</span> action = addItem({ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'T-Shirt'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">25</span> });
<span class="hljs-built_in">console</span>.log(action);  <span class="hljs-comment">// { type: 'cart/addItem', payload: { ... } }</span>
</code></pre>
<p><strong>3. Reducers</strong>: Pure functions that specify how state changes</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// A reducer is a function that takes current state and an action,</span>
<span class="hljs-comment">// and returns new state. It must NEVER modify the existing state.</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cartReducer</span>(<span class="hljs-params">state = { items: [], total: <span class="hljs-number">0</span> }, action</span>) </span>{
  <span class="hljs-comment">// state: current cart state</span>
  <span class="hljs-comment">// action: the action object describing what happened</span>

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'cart/addItem'</span>: {
      <span class="hljs-keyword">const</span> product = action.payload;

      <span class="hljs-comment">// NEVER modify existing state directly!</span>
      <span class="hljs-comment">// Instead, create new objects/arrays</span>
      <span class="hljs-keyword">return</span> {
        ...state,                                    <span class="hljs-comment">// Copy existing state</span>
        <span class="hljs-attr">items</span>: [...state.items, product],           <span class="hljs-comment">// Create new items array</span>
        <span class="hljs-attr">total</span>: state.total + product.price          <span class="hljs-comment">// Calculate new total</span>
      };
    }

    <span class="hljs-keyword">case</span> <span class="hljs-string">'cart/removeItem'</span>: {
      <span class="hljs-keyword">const</span> productId = action.payload;
      <span class="hljs-keyword">const</span> itemToRemove = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">items</span>: state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),  <span class="hljs-comment">// New array without item</span>
        <span class="hljs-attr">total</span>: state.total - (itemToRemove?.price || <span class="hljs-number">0</span>)           <span class="hljs-comment">// Subtract price</span>
      };
    }

    <span class="hljs-attr">default</span>:
      <span class="hljs-comment">// Always return current state for unknown actions</span>
      <span class="hljs-keyword">return</span> state;
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">userReducer</span>(<span class="hljs-params">state = { id: null, name: <span class="hljs-string">''</span>, isLoggedIn: false }, action</span>) </span>{
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'user/login'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        ...action.payload,    <span class="hljs-comment">// Merge user data from payload</span>
        <span class="hljs-attr">isLoggedIn</span>: <span class="hljs-literal">true</span>      <span class="hljs-comment">// Set login status</span>
      };

    <span class="hljs-keyword">case</span> <span class="hljs-string">'user/logout'</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">id</span>: <span class="hljs-literal">null</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">email</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">isLoggedIn</span>: <span class="hljs-literal">false</span>
      };

    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
}

<span class="hljs-comment">// Root reducer: combines all reducers</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rootReducer</span>(<span class="hljs-params">state = {}, action</span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">cart</span>: cartReducer(state.cart, action),    <span class="hljs-comment">// Handle cart actions</span>
    <span class="hljs-attr">user</span>: userReducer(state.user, action),    <span class="hljs-comment">// Handle user actions</span>
  };
}
</code></pre>
<p><strong>4. Dispatch</strong>: The only way to trigger state changes</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// You can't change Redux state directly</span>
<span class="hljs-comment">// Instead, you dispatch actions to describe what should happen</span>

<span class="hljs-comment">// Get the store's dispatch function</span>
<span class="hljs-keyword">const</span> { dispatch } = store;

<span class="hljs-comment">// Dispatch actions to change state</span>
dispatch(addItem({ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'T-Shirt'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">25</span> }));
dispatch(loginUser({ <span class="hljs-attr">id</span>: <span class="hljs-number">123</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">'alice@example.com'</span> }));
dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'user/logout'</span> });

<span class="hljs-comment">// Each dispatch triggers the reducer, which returns new state</span>
</code></pre>
<h4 id="heading-how-to-use-redux-in-react-components">How to use Redux in React components</h4>
<p>To use Redux in React, you need the <code>react-redux</code> library, which provides two main tools:</p>
<p><strong>1. Provider</strong>: Makes the store available to all components</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-comment">// Create your Redux store</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">// Provider makes the store available to all child components</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ProductList</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Cart</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>2. useSelector</strong> and <strong>useDispatch</strong> hooks</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductCard</span>(<span class="hljs-params">{ product }</span>) </span>{
  <span class="hljs-comment">// useSelector extracts data from the Redux store</span>
  <span class="hljs-comment">// The function you pass gets the entire state object</span>
  <span class="hljs-keyword">const</span> cartItems = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.cart.items);

  <span class="hljs-comment">// useDispatch returns the dispatch function</span>
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-comment">// Check if this product is already in cart</span>
  <span class="hljs-keyword">const</span> isInCart = cartItems.some(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === product.id);

  <span class="hljs-keyword">const</span> handleAddToCart = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Dispatch an action to add item</span>
    dispatch(addItem(product));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{product.description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"price"</span>&gt;</span>${product.price}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleAddToCart}</span>
        <span class="hljs-attr">disabled</span>=<span class="hljs-string">{isInCart}</span>
      &gt;</span>
        {isInCart ? 'In Cart' : 'Add to Cart'}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartSummary</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Select multiple pieces of state</span>
  <span class="hljs-keyword">const</span> { items, total } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({
    <span class="hljs-attr">items</span>: state.cart.items,
    <span class="hljs-attr">total</span>: state.cart.total
  }));

  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">const</span> handleRemoveItem = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    dispatch(removeItem(productId));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-summary"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Cart Summary<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Total: ${total.toFixed(2)}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      {items.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name} - ${item.price}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleRemoveItem(item.id)}&gt;
            Remove
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-redux-toolkit-modern-redux-made-simple">Redux Toolkit: Modern Redux made simple</h3>
<p><strong>Redux Toolkit</strong> is the official, recommended way to write Redux logic. It simplifies Redux by providing utilities that reduce boilerplate code.</p>
<h4 id="heading-what-redux-toolkit-provides">What Redux Toolkit provides</h4>
<ol>
<li><p><strong>createSlice</strong>: Generates action creators and reducers automatically</p>
</li>
<li><p><strong>configureStore</strong>: Sets up the store with good defaults</p>
</li>
<li><p><strong>Immer integration</strong>: Lets you write "mutative" logic that's actually immutable</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSlice, configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-comment">// createSlice generates action creators and reducers automatically</span>
<span class="hljs-keyword">const</span> cartSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'cart'</span>,                     <span class="hljs-comment">// Name for this slice of state</span>

  <span class="hljs-attr">initialState</span>: {                   <span class="hljs-comment">// Initial state value</span>
    <span class="hljs-attr">items</span>: [],
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>
  },

  <span class="hljs-attr">reducers</span>: {                       <span class="hljs-comment">// Reducer functions</span>
    <span class="hljs-comment">// Redux Toolkit uses Immer internally, so we can "mutate" state</span>
    <span class="hljs-comment">// (It's actually creating immutable updates behind the scenes)</span>

    <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> product = action.payload;
      <span class="hljs-keyword">const</span> existingItem = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === product.id);

      <span class="hljs-keyword">if</span> (existingItem) {
        existingItem.quantity += <span class="hljs-number">1</span>;              <span class="hljs-comment">// This looks like mutation!</span>
      } <span class="hljs-keyword">else</span> {
        state.items.push({                       <span class="hljs-comment">// This looks like mutation!</span>
          ...product, 
          <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> 
        });
      }

      state.total += product.price;              <span class="hljs-comment">// This looks like mutation!</span>
    },

    <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> productId = action.payload;
      <span class="hljs-keyword">const</span> itemIndex = state.items.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">if</span> (itemIndex &gt;= <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> item = state.items[itemIndex];
        state.total -= item.price * item.quantity;
        state.items.splice(itemIndex, <span class="hljs-number">1</span>);        <span class="hljs-comment">// Remove from array</span>
      }
    },

    <span class="hljs-attr">updateQuantity</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> { productId, quantity } = action.payload;
      <span class="hljs-keyword">const</span> item = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">if</span> (item) {
        <span class="hljs-keyword">const</span> quantityDiff = quantity - item.quantity;
        item.quantity = quantity;                <span class="hljs-comment">// Update quantity</span>
        state.total += item.price * quantityDiff; <span class="hljs-comment">// Update total</span>
      }
    }
  }
});

<span class="hljs-comment">// Export action creators (automatically generated by createSlice)</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addItem, removeItem, updateQuantity } = cartSlice.actions;

<span class="hljs-comment">// Create the store with configureStore</span>
<span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">cart</span>: cartSlice.reducer,        <span class="hljs-comment">// Add cart reducer to store</span>
    <span class="hljs-comment">// You can add more reducers here</span>
  }
});

<span class="hljs-comment">// Usage in components (same as regular Redux)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ShoppingCart</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Note: state.cart because we named it 'cart' in configureStore</span>
  <span class="hljs-keyword">const</span> { items, total } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.cart);
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Shopping Cart<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Total: ${total.toFixed(2)}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      {items.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name} - Qty: {item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(removeItem(item.id))}&gt;
            Remove
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
            <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> 
            <span class="hljs-attr">value</span>=<span class="hljs-string">{item.quantity}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> dispatch(updateQuantity({
              productId: item.id, 
              quantity: parseInt(e.target.value)
            }))}
          /&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Redux Toolkit is better than vanilla Redux for a few key reasons:</p>
<ol>
<li><p><strong>Less boilerplate</strong>: No need to write action creators manually</p>
</li>
<li><p><strong>Immer integration</strong>: Write code that looks like mutations but is actually immutable</p>
</li>
<li><p><strong>Better defaults</strong>: configureStore includes useful middleware automatically</p>
</li>
<li><p><strong>TypeScript friendly</strong>: Better type inference and support</p>
</li>
<li><p><strong>DevTools included</strong>: Redux DevTools work automatically</p>
</li>
</ol>
<h3 id="heading-zustand-simple-and-flexible-state-management">Zustand: Simple and flexible state management</h3>
<p><strong>Zustand</strong> is a lightweight state management library that's much simpler than Redux but more powerful than Context for complex state.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { create } <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand'</span>;

<span class="hljs-comment">// Create a store with state and actions in one place</span>
<span class="hljs-keyword">const</span> useCartStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-comment">// Initial state</span>
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,

  <span class="hljs-comment">// Actions (functions that update state)</span>
  <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> existingItem = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === product.id);

    <span class="hljs-keyword">if</span> (existingItem) {
      <span class="hljs-comment">// Update existing item quantity</span>
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">items</span>: state.items.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span>
          item.id === product.id 
            ? { ...item, <span class="hljs-attr">quantity</span>: item.quantity + <span class="hljs-number">1</span> }
            : item
        ),
        <span class="hljs-attr">total</span>: state.total + product.price
      };
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// Add new item</span>
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">items</span>: [...state.items, { ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
        <span class="hljs-attr">total</span>: state.total + product.price
      };
    }
  }),

  <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> itemToRemove = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);
    <span class="hljs-keyword">if</span> (!itemToRemove) <span class="hljs-keyword">return</span> state;

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">items</span>: state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),
      <span class="hljs-attr">total</span>: state.total - (itemToRemove.price * itemToRemove.quantity)
    };
  }),

  <span class="hljs-attr">clearCart</span>: <span class="hljs-function">() =&gt;</span> set({ <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> }),

  <span class="hljs-comment">// Computed values (getters)</span>
  <span class="hljs-keyword">get</span> <span class="hljs-title">itemCount</span>() {
    <span class="hljs-keyword">return</span> get().items.reduce(<span class="hljs-function">(<span class="hljs-params">count, item</span>) =&gt;</span> count + item.quantity, <span class="hljs-number">0</span>);
  }
}));

<span class="hljs-comment">// Usage in components - very clean</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductCard</span>(<span class="hljs-params">{ product }</span>) </span>{
  <span class="hljs-comment">// Only get the function we need</span>
  <span class="hljs-keyword">const</span> addItem = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.addItem);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>${product.price}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addItem(product)}&gt;
        Add to Cart
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Only get the computed value we need</span>
  <span class="hljs-keyword">const</span> itemCount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.itemCount);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      Cart ({itemCount})
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartList</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Get multiple values at once</span>
  <span class="hljs-keyword">const</span> { items, total, removeItem } = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({
    <span class="hljs-attr">items</span>: state.items,
    <span class="hljs-attr">total</span>: state.total,
    <span class="hljs-attr">removeItem</span>: state.removeItem
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-list"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Your Cart - Total: ${total.toFixed(2)}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      {items.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name} x {item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeItem(item.id)}&gt;
            Remove
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>What makes Zustand special:</p>
<ol>
<li><p><strong>No boilerplate</strong>: Define state and actions in one place</p>
</li>
<li><p><strong>No providers</strong>: No need to wrap your app in a Provider component</p>
</li>
<li><p><strong>TypeScript friendly</strong>: Excellent TypeScript support out of the box</p>
</li>
<li><p><strong>Small bundle</strong>: Much smaller than Redux</p>
</li>
<li><p><strong>Simple mental model</strong>: Just hooks that return state and functions</p>
</li>
</ol>
<h4 id="heading-advanced-zustand-patterns">Advanced Zustand patterns</h4>
<p>Persistence and middleware:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { create } <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand'</span>;
<span class="hljs-keyword">import</span> { persist, devtools } <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand/middleware'</span>;

<span class="hljs-comment">// Store with localStorage persistence and Redux DevTools</span>
<span class="hljs-keyword">const</span> useCartStore = create(
  devtools(                        <span class="hljs-comment">// Adds Redux DevTools support</span>
    persist(                       <span class="hljs-comment">// Adds localStorage persistence</span>
      <span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
        <span class="hljs-attr">items</span>: [],
        <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,

        <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(
          <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
            <span class="hljs-attr">items</span>: [...state.items, { ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
            <span class="hljs-attr">total</span>: state.total + product.price
          }),
          <span class="hljs-literal">false</span>,                   <span class="hljs-comment">// Don't replace entire state</span>
          <span class="hljs-string">'cart/addItem'</span>           <span class="hljs-comment">// Action name for dev tools</span>
        ),

        <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> set(
          <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> itemToRemove = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);
            <span class="hljs-keyword">return</span> {
              <span class="hljs-attr">items</span>: state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),
              <span class="hljs-attr">total</span>: state.total - (itemToRemove?.price || <span class="hljs-number">0</span>)
            };
          },
          <span class="hljs-literal">false</span>,
          <span class="hljs-string">'cart/removeItem'</span>
        )
      }),
      {
        <span class="hljs-attr">name</span>: <span class="hljs-string">'cart-storage'</span>,      <span class="hljs-comment">// localStorage key</span>
        <span class="hljs-attr">getStorage</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">localStorage</span>, <span class="hljs-comment">// Storage method</span>
      }
    )
  )
);

<span class="hljs-comment">// Subscriptions for side effects</span>
useCartStore.subscribe(
  <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.items,          <span class="hljs-comment">// Watch items array</span>
  <span class="hljs-function">(<span class="hljs-params">items</span>) =&gt;</span> {                     <span class="hljs-comment">// Callback when items change</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Cart items updated:'</span>, items);

    <span class="hljs-comment">// Update browser tab title</span>
    <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`Shopping (<span class="hljs-subst">${items.length}</span>) - MyStore`</span>;

    <span class="hljs-comment">// Track analytics</span>
    analytics.track(<span class="hljs-string">'Cart Updated'</span>, {
      <span class="hljs-attr">itemCount</span>: items.length,
      <span class="hljs-attr">cartValue</span>: items.reduce(<span class="hljs-function">(<span class="hljs-params">sum, item</span>) =&gt;</span> sum + item.price * item.quantity, <span class="hljs-number">0</span>)
    });
  }
);
</code></pre>
<h2 id="heading-performance-optimization-strategies-explained">Performance Optimization Strategies Explained</h2>
<p>Shared state can cause performance issues when components re-render unnecessarily. Let's understand why this happens and how to prevent it.</p>
<h3 id="heading-why-do-unnecessary-re-renders-happen">Why do unnecessary re-renders happen?</h3>
<p><strong>Here’s the fundamental issue</strong>: in React, when state changes, all components that use that state re-render, even if they don't actually display the changed data.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Problem: This context causes ALL consumers to re-render when ANY value changes</span>
<span class="hljs-keyword">const</span> AppContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AppProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">'alice@example.com'</span> });
  <span class="hljs-keyword">const</span> [cart, setCart] = useState({ <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> });
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);

  <span class="hljs-comment">// When ANY of these values change, ALL components using useContext(AppContext) re-render</span>
  <span class="hljs-keyword">const</span> value = {
    user, setUser,
    cart, setCart, 
    theme, setTheme
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// This component only cares about theme, but re-renders when user or cart change</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeToggle</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme, setTheme } = useContext(AppContext);  <span class="hljs-comment">// Gets ALL context data</span>

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'ThemeToggle rendering'</span>);  <span class="hljs-comment">// This logs every time ANY context value changes</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTheme(theme === 'light' ? 'dark' : 'light')}&gt;
      Current theme: {theme}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-solution-1-split-contexts-to-minimize-re-renders">Solution 1: Split contexts to minimize re-renders</h3>
<p>You can split large contexts into smaller, focused ones like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Instead of one large context, create separate contexts</span>
<span class="hljs-keyword">const</span> UserContext = createContext();
<span class="hljs-keyword">const</span> CartContext = createContext();  
<span class="hljs-keyword">const</span> ThemeContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">'alice@example.com'</span> });

  <span class="hljs-comment">// Only components using UserContext re-render when user changes</span>
  <span class="hljs-keyword">const</span> value = { user, setUser };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);

  <span class="hljs-comment">// Only components using ThemeContext re-render when theme changes</span>
  <span class="hljs-keyword">const</span> value = { theme, setTheme };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Now ThemeToggle only re-renders when theme changes</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeToggle</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme, setTheme } = useContext(ThemeContext);  <span class="hljs-comment">// Only theme data</span>

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'ThemeToggle rendering'</span>);  <span class="hljs-comment">// Only logs when theme changes</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTheme(theme === 'light' ? 'dark' : 'light')}&gt;
      Current theme: {theme}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-solution-2-memoize-context-values-to-prevent-object-recreation">Solution 2: Memoize context values to prevent object recreation</h3>
<p>The problem is that creating new objects in render causes unnecessary re-renders:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Creates new objects every render</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
      // <span class="hljs-attr">This</span> <span class="hljs-attr">creates</span> <span class="hljs-attr">a</span> <span class="hljs-attr">NEW</span> <span class="hljs-attr">object</span> <span class="hljs-attr">every</span> <span class="hljs-attr">time</span> <span class="hljs-attr">CartProvider</span> <span class="hljs-attr">renders</span>!
      <span class="hljs-attr">items</span>,                      // <span class="hljs-attr">Same</span> <span class="hljs-attr">value</span>, <span class="hljs-attr">but</span> <span class="hljs-attr">new</span> <span class="hljs-attr">object</span> <span class="hljs-attr">reference</span>
      <span class="hljs-attr">total</span>,                      // <span class="hljs-attr">Same</span> <span class="hljs-attr">value</span>, <span class="hljs-attr">but</span> <span class="hljs-attr">new</span> <span class="hljs-attr">object</span> <span class="hljs-attr">reference</span>
      <span class="hljs-attr">addItem:</span> (<span class="hljs-attr">item</span>) =&gt;</span> {        // NEW function every render!
        setItems([...items, item]);
      },
      removeItem: (id) =&gt; {       // NEW function every render!
        setItems(items.filter(item =&gt; item.id !== id));
      }
    }}&gt;
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p>This is bad because React uses <code>Object.is()</code> to compare context values. Even if the data is the same, a new object means all consumers re-render.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ CORRECT: Memoize the context value</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-comment">// useCallback memoizes functions - they only change when dependencies change</span>
  <span class="hljs-keyword">const</span> addItem = useCallback(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prevItems</span> =&gt;</span> [...prevItems, item]);  <span class="hljs-comment">// Use function update</span>
  }, []);  <span class="hljs-comment">// Empty dependency array means this function never changes</span>

  <span class="hljs-keyword">const</span> removeItem = useCallback(<span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prevItems</span> =&gt;</span> prevItems.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== id));
  }, []);

  <span class="hljs-comment">// useMemo memoizes the context value object</span>
  <span class="hljs-keyword">const</span> value = useMemo(<span class="hljs-function">() =&gt;</span> ({
    items,
    total,
    addItem,
    removeItem
  }), [items, total, addItem, removeItem]);  <span class="hljs-comment">// Only create new object when these change</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p>What useCallback and useMemo do:</p>
<ul>
<li><p><strong>useCallback(fn, deps)</strong>: Returns a memoized function that only changes when dependencies change</p>
</li>
<li><p><strong>useMemo(fn, deps)</strong>: Returns a memoized value that only recalculates when dependencies change</p>
</li>
</ul>
<h3 id="heading-solution-3-select-only-what-you-need">Solution 3: Select only what you need</h3>
<p>With Redux/Zustand, make sure you’re selective about what data you subscribe to:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Component re-renders when ANY cart data changes</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { items, total, addItem, removeItem } = useCartStore();  <span class="hljs-comment">// Gets everything!</span>

  <span class="hljs-comment">// This component only shows item count, but re-renders when total changes</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      Cart ({items.length})
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// ✅ CORRECT: Only subscribe to what you need</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Only re-renders when items array changes</span>
  <span class="hljs-keyword">const</span> itemCount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.items.length);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      Cart ({itemCount})
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// ✅ EVEN BETTER: Use a selector for computed values</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Only re-renders when the computed itemCount changes</span>
  <span class="hljs-keyword">const</span> itemCount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> 
    state.items.reduce(<span class="hljs-function">(<span class="hljs-params">count, item</span>) =&gt;</span> count + item.quantity, <span class="hljs-number">0</span>)
  );

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>
      Cart ({itemCount})
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-solution-4-use-reactmemo-for-expensive-components">Solution 4: Use React.memo for expensive components</h3>
<p><strong>React.memo</strong> prevents component re-renders when props haven't changed:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Expensive component that does heavy calculations</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExpensiveProductList</span>(<span class="hljs-params">{ products, onAddToCart }</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'ExpensiveProductList rendering'</span>);  <span class="hljs-comment">// This should log rarely</span>

  <span class="hljs-comment">// Simulate expensive calculation</span>
  <span class="hljs-keyword">const</span> processedProducts = products.map(<span class="hljs-function"><span class="hljs-params">product</span> =&gt;</span> ({
    ...product,
    <span class="hljs-attr">discountedPrice</span>: product.price * <span class="hljs-number">0.9</span>,
    <span class="hljs-attr">categories</span>: product.categories.sort(),
    <span class="hljs-comment">// ... more expensive operations</span>
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product-list"</span>&gt;</span>
      {processedProducts.map(product =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: ${product.discountedPrice}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> onAddToCart(product)}&gt;
            Add to Cart
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// ❌ Without memo: Re-renders every time parent renders</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpensiveProductList;

<span class="hljs-comment">// ✅ With memo: Only re-renders when props actually change</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> React.memo(ExpensiveProductList);

<span class="hljs-comment">// ✅ With custom comparison: You control when it re-renders</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> React.memo(ExpensiveProductList, <span class="hljs-function">(<span class="hljs-params">prevProps, nextProps</span>) =&gt;</span> {
  <span class="hljs-comment">// Return true if props are equal (skip re-render)</span>
  <span class="hljs-comment">// Return false if props are different (re-render)</span>

  <span class="hljs-keyword">return</span> (
    prevProps.products.length === nextProps.products.length &amp;&amp;
    prevProps.onAddToCart === nextProps.onAddToCart
  );
});
</code></pre>
<h3 id="heading-solution-5-optimize-with-custom-selector-hooks">Solution 5: Optimize with custom selector hooks</h3>
<p>You can create reusable selector hooks for common patterns:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Custom hook that memoizes selectors</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCartSelector</span>(<span class="hljs-params">selector</span>) </span>{
  <span class="hljs-keyword">const</span> selectedValue = useCartStore(selector);

  <span class="hljs-comment">// The selector itself should be memoized to prevent unnecessary re-renders</span>
  <span class="hljs-keyword">return</span> useMemo(<span class="hljs-function">() =&gt;</span> selectedValue, [selectedValue]);
}

<span class="hljs-comment">// Pre-defined selectors for common use cases</span>
<span class="hljs-keyword">const</span> selectItemCount = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.items.length;
<span class="hljs-keyword">const</span> selectTotal = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.total;
<span class="hljs-keyword">const</span> selectIsEmpty = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.items.length === <span class="hljs-number">0</span>;
<span class="hljs-keyword">const</span> selectItemById = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === id);

<span class="hljs-comment">// Usage in components</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> itemCount = useCartStore(selectItemCount);  <span class="hljs-comment">// Only re-renders when count changes</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-badge"</span>&gt;</span>{itemCount}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartTotal</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> total = useCartStore(selectTotal);  <span class="hljs-comment">// Only re-renders when total changes</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-total"</span>&gt;</span>
      Total: ${total.toFixed(2)}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductInCart</span>(<span class="hljs-params">{ productId }</span>) </span>{
  <span class="hljs-comment">// This selector is created with the specific productId</span>
  <span class="hljs-keyword">const</span> selectThisItem = useMemo(
    <span class="hljs-function">() =&gt;</span> <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId),
    [productId]
  );

  <span class="hljs-keyword">const</span> item = useCartStore(selectThisItem);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {item ? `In cart: ${item.quantity}` : 'Not in cart'}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-testing-shared-state-a-comprehensive-approach">Testing Shared State: A Comprehensive Approach</h2>
<p>Testing shared state requires different approaches than testing isolated components. Let's explore why this is more complex and what specific strategies we need.</p>
<h3 id="heading-why-shared-state-testing-is-different">Why shared state testing is different</h3>
<p>When testing isolated components, you typically pass props directly to the component, mock external dependencies, and test the component's output based on specific inputs.</p>
<p>But with shared state, you face additional challenges:</p>
<ul>
<li><p><strong>Dependencies on external state</strong>: Components depend on Context, Redux stores, or global state that must be provided</p>
</li>
<li><p><strong>State synchronization</strong>: You need to test that multiple components stay in sync when state changes</p>
</li>
<li><p><strong>Provider setup</strong>: Components using Context will crash without proper Provider wrappers</p>
</li>
<li><p><strong>State mutations</strong>: Testing that state updates correctly across multiple components</p>
</li>
<li><p><strong>Integration behavior</strong>: Ensuring the entire state management system works together</p>
</li>
</ul>
<p>This means you’ll need different testing strategies. You’ll need to provide the correct state management infrastructure, test how changes in one component affect others, gracefully handle loading states, errors, and async operations, and test that optimizations work correctly.</p>
<p>Let's explore each approach thoroughly.</p>
<h3 id="heading-testing-react-context">Testing React Context</h3>
<p><strong>The challenge</strong>: Components using Context need a Provider to work, and you need to test both the Context logic and component behavior.</p>
<p><strong>Why Context testing is unique:</strong> Unlike regular components that receive props directly, Context consumers depend on a Provider being present in the component tree. This creates several testing challenges:</p>
<ol>
<li><p>Components will crash if used outside a Provider</p>
</li>
<li><p>Each test needs its own Provider instance to avoid test interference</p>
</li>
<li><p>You need to test that Provider and Consumer work together correctly</p>
</li>
<li><p>Testing <code>useContext</code> hooks requires special setup</p>
</li>
</ol>
<p>Let’s see some strategies specific to Context.</p>
<h4 id="heading-setting-up-context-tests">Setting up Context tests:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen, fireEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { createContext, useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Our Context setup (same as before)</span>
<span class="hljs-keyword">const</span> CartContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCart</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> context = useContext(CartContext);
  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useCart must be used within a CartProvider'</span>);
  }
  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> addItem = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> [...prev, product]);
    setTotal(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> prev + product.price);
  };

  <span class="hljs-keyword">const</span> removeItem = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> updatedItems = prev.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);
      <span class="hljs-keyword">const</span> removedItem = prev.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">if</span> (removedItem) {
        setTotal(<span class="hljs-function"><span class="hljs-params">current</span> =&gt;</span> current - removedItem.price);
      }

      <span class="hljs-keyword">return</span> updatedItems;
    });
  };

  <span class="hljs-keyword">const</span> value = { items, total, addItem, removeItem };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Test component that uses our Context</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TestCartComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { items, total, addItem, removeItem } = useCart();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"item-count"</span>&gt;</span>{items.length}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"total"</span>&gt;</span>${total.toFixed(2)}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addItem({ id: 1, name: 'Test Product', price: 10 })}
        data-testid="add-item"
      &gt;
        Add Item
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      {items.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">item-</span>${<span class="hljs-attr">item.id</span>}`}&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeItem(item.id)}
            data-testid={`remove-${item.id}`}
          &gt;
            Remove
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Helper function to render components with CartProvider</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">renderWithCartProvider</span>(<span class="hljs-params">component</span>) </span>{
  <span class="hljs-keyword">return</span> render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartProvider</span>&gt;</span>
      {component}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartProvider</span>&gt;</span></span>
  );
}
</code></pre>
<h4 id="heading-writing-context-tests">Writing Context tests:</h4>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'Cart Context functionality'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should start with empty cart'</span>, <span class="hljs-function">() =&gt;</span> {
    renderWithCartProvider(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);

    <span class="hljs-comment">// Check initial state</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'0'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'total'</span>)).toHaveTextContent(<span class="hljs-string">'$0.00'</span>);
  });

  test(<span class="hljs-string">'should add item to cart'</span>, <span class="hljs-function">() =&gt;</span> {
    renderWithCartProvider(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);

    <span class="hljs-comment">// Click the add button</span>
    <span class="hljs-keyword">const</span> addButton = screen.getByTestId(<span class="hljs-string">'add-item'</span>);
    fireEvent.click(addButton);

    <span class="hljs-comment">// Verify item was added</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'1'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'total'</span>)).toHaveTextContent(<span class="hljs-string">'$10.00'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'item-1'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'Test Product'</span>)).toBeInTheDocument();
  });

  test(<span class="hljs-string">'should remove item from cart'</span>, <span class="hljs-function">() =&gt;</span> {
    renderWithCartProvider(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);

    <span class="hljs-comment">// Add item first</span>
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'add-item'</span>));

    <span class="hljs-comment">// Verify item is there</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'1'</span>);

    <span class="hljs-comment">// Remove the item</span>
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'remove-1'</span>));

    <span class="hljs-comment">// Verify item was removed</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'0'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'total'</span>)).toHaveTextContent(<span class="hljs-string">'$0.00'</span>);
    expect(screen.queryByTestId(<span class="hljs-string">'item-1'</span>)).not.toBeInTheDocument();
  });

  test(<span class="hljs-string">'should handle multiple items'</span>, <span class="hljs-function">() =&gt;</span> {
    renderWithCartProvider(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);

    <span class="hljs-comment">// Add multiple items</span>
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'add-item'</span>));
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'add-item'</span>));
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'add-item'</span>));

    <span class="hljs-comment">// Verify count and total</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'3'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'total'</span>)).toHaveTextContent(<span class="hljs-string">'$30.00'</span>);
  });

  test(<span class="hljs-string">'should throw error when used outside provider'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Mock console.error to avoid error output in tests</span>
    <span class="hljs-keyword">const</span> consoleSpy = jest.spyOn(<span class="hljs-built_in">console</span>, <span class="hljs-string">'error'</span>).mockImplementation(<span class="hljs-function">() =&gt;</span> {});

    <span class="hljs-comment">// This should throw an error</span>
    expect(<span class="hljs-function">() =&gt;</span> {
      render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);  <span class="hljs-comment">// No CartProvider wrapper</span>
    }).toThrow(<span class="hljs-string">'useCart must be used within a CartProvider'</span>);

    consoleSpy.mockRestore();
  });

  test(<span class="hljs-string">'should handle edge cases'</span>, <span class="hljs-function">() =&gt;</span> {
    renderWithCartProvider(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span></span>);

    <span class="hljs-comment">// Try to remove item that doesn't exist</span>
    <span class="hljs-keyword">const</span> initialCount = screen.getByTestId(<span class="hljs-string">'item-count'</span>).textContent;

    <span class="hljs-comment">// This shouldn't crash or change anything</span>
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'add-item'</span>));
    fireEvent.click(screen.getByTestId(<span class="hljs-string">'remove-999'</span>));  <span class="hljs-comment">// Non-existent item</span>

    <span class="hljs-comment">// Count should still be 1</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'1'</span>);
  });
});
</code></pre>
<h4 id="heading-testing-context-with-different-initial-states">Testing Context with different initial states:</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// Custom Provider for testing with specific initial state</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TestCartProvider</span>(<span class="hljs-params">{ children, initialItems = [], initialTotal = <span class="hljs-number">0</span> }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState(initialItems);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(initialTotal);

  <span class="hljs-comment">// Same logic as CartProvider</span>
  <span class="hljs-keyword">const</span> addItem = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> [...prev, product]);
    setTotal(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> prev + product.price);
  };

  <span class="hljs-keyword">const</span> removeItem = <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prev</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> updatedItems = prev.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId);
      <span class="hljs-keyword">const</span> removedItem = prev.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">if</span> (removedItem) {
        setTotal(<span class="hljs-function"><span class="hljs-params">current</span> =&gt;</span> current - removedItem.price);
      }

      <span class="hljs-keyword">return</span> updatedItems;
    });
  };

  <span class="hljs-keyword">const</span> value = { items, total, addItem, removeItem };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}

describe(<span class="hljs-string">'Cart Context with initial state'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should work with pre-populated cart'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> initialItems = [
      { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Existing Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">15</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Another Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">25</span> }
    ];

    render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestCartProvider</span> <span class="hljs-attr">initialItems</span>=<span class="hljs-string">{initialItems}</span> <span class="hljs-attr">initialTotal</span>=<span class="hljs-string">{40}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TestCartComponent</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">TestCartProvider</span>&gt;</span></span>
    );

    <span class="hljs-comment">// Should show existing items</span>
    expect(screen.getByTestId(<span class="hljs-string">'item-count'</span>)).toHaveTextContent(<span class="hljs-string">'2'</span>);
    expect(screen.getByTestId(<span class="hljs-string">'total'</span>)).toHaveTextContent(<span class="hljs-string">'$40.00'</span>);
    expect(screen.getByText(<span class="hljs-string">'Existing Product'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'Another Product'</span>)).toBeInTheDocument();
  });
});
</code></pre>
<h3 id="heading-testing-redux-stores">Testing Redux stores</h3>
<p><strong>Why Redux testing requires different approaches:</strong> Redux introduces a predictable but complex state management system that needs testing at multiple levels:</p>
<ol>
<li><p><strong>Pure function testing</strong>: Reducers are pure functions that can be tested in isolation</p>
</li>
<li><p><strong>Action creator testing</strong>: Ensuring actions are created correctly</p>
</li>
<li><p><strong>Connected component testing</strong>: Components that use <code>useSelector</code> and <code>useDispatch</code> need store setup</p>
</li>
<li><p><strong>Integration testing</strong>: Testing the entire Redux flow from action dispatch to state update to component re-render</p>
</li>
<li><p><strong>Async action testing</strong>: Testing thunks, sagas, or other async middleware</p>
</li>
</ol>
<p>Redux testing focuses on three areas: action creators, reducers, and connected components.</p>
<h4 id="heading-testing-reducers-pure-functions">Testing reducers (pure functions):</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> cartReducer, { addItem, removeItem, updateQuantity } <span class="hljs-keyword">from</span> <span class="hljs-string">'./cartSlice'</span>;

describe(<span class="hljs-string">'Cart reducer'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">items</span>: [],
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>
  };

  test(<span class="hljs-string">'should return initial state when called with undefined'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Reducer should handle undefined state</span>
    <span class="hljs-keyword">const</span> result = cartReducer(<span class="hljs-literal">undefined</span>, { <span class="hljs-attr">type</span>: <span class="hljs-string">'unknown'</span> });
    expect(result).toEqual(initialState);
  });

  test(<span class="hljs-string">'should handle addItem action'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> product = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> };
    <span class="hljs-keyword">const</span> action = addItem(product);

    <span class="hljs-keyword">const</span> result = cartReducer(initialState, action);

    expect(result).toEqual({
      <span class="hljs-attr">items</span>: [{ ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">10</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    });

    <span class="hljs-comment">// Original state should be unchanged (immutability test)</span>
    expect(initialState.items).toHaveLength(<span class="hljs-number">0</span>);
  });

  test(<span class="hljs-string">'should increase quantity for existing item'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> existingState = {
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">10</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    };

    <span class="hljs-keyword">const</span> product = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> };
    <span class="hljs-keyword">const</span> action = addItem(product);

    <span class="hljs-keyword">const</span> result = cartReducer(existingState, action);

    expect(result).toEqual({
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">20</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">2</span>
    });
  });

  test(<span class="hljs-string">'should handle removeItem action'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> existingState = {
      <span class="hljs-attr">items</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Product 1'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Product 2'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">15</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }
      ],
      <span class="hljs-attr">total</span>: <span class="hljs-number">35</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">3</span>
    };

    <span class="hljs-keyword">const</span> action = removeItem(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">const</span> result = cartReducer(existingState, action);

    expect(result).toEqual({
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Product 2'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">15</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">15</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    });
  });

  test(<span class="hljs-string">'should handle updateQuantity action'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> existingState = {
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">20</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">2</span>
    };

    <span class="hljs-keyword">const</span> action = updateQuantity({ <span class="hljs-attr">productId</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">5</span> });
    <span class="hljs-keyword">const</span> result = cartReducer(existingState, action);

    expect(result).toEqual({
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">5</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">50</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">5</span>
    });
  });

  test(<span class="hljs-string">'should remove item when quantity is set to 0'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> existingState = {
      <span class="hljs-attr">items</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">20</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">2</span>
    };

    <span class="hljs-keyword">const</span> action = updateQuantity({ <span class="hljs-attr">productId</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">0</span> });
    <span class="hljs-keyword">const</span> result = cartReducer(existingState, action);

    expect(result).toEqual({
      <span class="hljs-attr">items</span>: [],
      <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>
    });
  });
});
</code></pre>
<h4 id="heading-testing-redux-connected-components">Testing Redux-connected components:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen, fireEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;
<span class="hljs-keyword">import</span> cartReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./cartSlice'</span>;
<span class="hljs-keyword">import</span> ConnectedProductCard <span class="hljs-keyword">from</span> <span class="hljs-string">'./ProductCard'</span>;

<span class="hljs-comment">// Helper to create a test store with initial state</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTestStore</span>(<span class="hljs-params">initialState = {}</span>) </span>{
  <span class="hljs-keyword">return</span> configureStore({
    <span class="hljs-attr">reducer</span>: {
      <span class="hljs-attr">cart</span>: cartReducer
    },
    <span class="hljs-attr">preloadedState</span>: {
      <span class="hljs-attr">cart</span>: {
        <span class="hljs-attr">items</span>: [],
        <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>,
        ...initialState
      }
    }
  });
}

<span class="hljs-comment">// Helper to render components with Redux store</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">renderWithStore</span>(<span class="hljs-params">component, store</span>) </span>{
  <span class="hljs-keyword">return</span> render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      {component}
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
}

describe(<span class="hljs-string">'ConnectedProductCard'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> mockProduct = {
    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-number">25</span>,
    <span class="hljs-attr">description</span>: <span class="hljs-string">'A test product'</span>
  };

  test(<span class="hljs-string">'should display product information'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = createTestStore();

    renderWithStore(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ConnectedProductCard</span> <span class="hljs-attr">product</span>=<span class="hljs-string">{mockProduct}</span> /&gt;</span></span>, store);

    expect(screen.getByText(<span class="hljs-string">'Test Product'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'$25'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'A test product'</span>)).toBeInTheDocument();
  });

  test(<span class="hljs-string">'should add item to cart when button clicked'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = createTestStore();

    renderWithStore(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ConnectedProductCard</span> <span class="hljs-attr">product</span>=<span class="hljs-string">{mockProduct}</span> /&gt;</span></span>, store);

    <span class="hljs-comment">// Initially, cart should be empty</span>
    expect(store.getState().cart.items).toHaveLength(<span class="hljs-number">0</span>);

    <span class="hljs-comment">// Click add to cart button</span>
    fireEvent.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/add to cart/i</span> }));

    <span class="hljs-comment">// Check that item was added to store</span>
    <span class="hljs-keyword">const</span> cartState = store.getState().cart;
    expect(cartState.items).toHaveLength(<span class="hljs-number">1</span>);
    expect(cartState.items[<span class="hljs-number">0</span>]).toEqual({ ...mockProduct, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> });
    expect(cartState.total).toBe(<span class="hljs-number">25</span>);
  });

  test(<span class="hljs-string">'should show "In Cart" when item is already in cart'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = createTestStore({
      <span class="hljs-attr">items</span>: [{ ...mockProduct, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
      <span class="hljs-attr">total</span>: <span class="hljs-number">25</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    });

    renderWithStore(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ConnectedProductCard</span> <span class="hljs-attr">product</span>=<span class="hljs-string">{mockProduct}</span> /&gt;</span></span>, store);

    <span class="hljs-comment">// Button should be disabled and show "In Cart"</span>
    <span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">'button'</span>);
    expect(button).toBeDisabled();
    expect(button).toHaveTextContent(<span class="hljs-string">'In Cart'</span>);
  });
});
</code></pre>
<h4 id="heading-integration-testing-with-multiple-connected-components">Integration testing with multiple connected components:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen, fireEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { createTestStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'./test-utils'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

describe(<span class="hljs-string">'Cart integration'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should update cart badge when item is added'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = createTestStore();

    render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
    );

    <span class="hljs-comment">// Initially, no cart badge should be visible</span>
    expect(screen.queryByText(<span class="hljs-regexp">/cart \(/</span>)).not.toBeInTheDocument();

    <span class="hljs-comment">// Add a product to cart</span>
    <span class="hljs-keyword">const</span> addButton = screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/add to cart/i</span> });
    fireEvent.click(addButton);

    <span class="hljs-comment">// Cart badge should now show 1 item</span>
    expect(screen.getByText(<span class="hljs-string">'Cart (1)'</span>)).toBeInTheDocument();
  });

  test(<span class="hljs-string">'should show cart items when cart dropdown is opened'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> store = createTestStore({
      <span class="hljs-attr">items</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }
      ],
      <span class="hljs-attr">total</span>: <span class="hljs-number">10</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    });

    render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
    );

    <span class="hljs-comment">// Open cart dropdown</span>
    fireEvent.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/cart/i</span> }));

    <span class="hljs-comment">// Should show cart item</span>
    expect(screen.getByText(<span class="hljs-string">'Test Product'</span>)).toBeInTheDocument();
    expect(screen.getByText(<span class="hljs-string">'$10.00'</span>)).toBeInTheDocument();
  });

  test(<span class="hljs-string">'should remove item when remove button is clicked'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = createTestStore({
      <span class="hljs-attr">items</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }
      ],
      <span class="hljs-attr">total</span>: <span class="hljs-number">10</span>,
      <span class="hljs-attr">itemCount</span>: <span class="hljs-number">1</span>
    });

    render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
    );

    <span class="hljs-comment">// Open cart dropdown</span>
    fireEvent.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/cart/i</span> }));

    <span class="hljs-comment">// Remove the item</span>
    fireEvent.click(screen.getByRole(<span class="hljs-string">'button'</span>, { <span class="hljs-attr">name</span>: <span class="hljs-regexp">/remove/i</span> }));

    <span class="hljs-comment">// Item should be gone</span>
    expect(screen.queryByText(<span class="hljs-string">'Test Product'</span>)).not.toBeInTheDocument();

    <span class="hljs-comment">// Cart badge should be gone</span>
    expect(screen.queryByText(<span class="hljs-regexp">/cart \(/</span>)).not.toBeInTheDocument();
  });
});
</code></pre>
<h3 id="heading-testing-custom-hooks-for-state-management">Testing custom hooks for state management:</h3>
<p><strong>Why custom hook testing is unique:</strong> Custom hooks can't be tested like regular functions because they use React hooks internally, which can only be called within React components. This creates specific testing challenges:</p>
<ol>
<li><p><strong>React context requirement</strong>: Hooks must be called within a React component or test environment</p>
</li>
<li><p><strong>State persistence</strong>: Testing that state persists correctly between renders</p>
</li>
<li><p><strong>Effect testing</strong>: Testing useEffect cleanup and dependency changes</p>
</li>
<li><p><strong>Isolation</strong>: Testing hook logic separately from UI components</p>
</li>
<li><p><strong>Multiple render cycles</strong>: Testing how hooks behave across re-renders</p>
</li>
</ol>
<p>You’ll need some special testing utilities:</p>
<ul>
<li><p><code>renderHook()</code>: Renders a hook in a test component</p>
</li>
<li><p><code>act()</code>: Ensures state updates are processed before assertions</p>
</li>
<li><p>Mock timers for testing delayed effects</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { renderHook, act } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> { useCart } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useCart'</span>;

describe(<span class="hljs-string">'useCart hook'</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">'should initialize with empty cart'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCart());

    expect(result.current.items).toEqual([]);
    expect(result.current.total).toBe(<span class="hljs-number">0</span>);
    expect(result.current.itemCount).toBe(<span class="hljs-number">0</span>);
  });

  test(<span class="hljs-string">'should add item to cart'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCart());

    <span class="hljs-keyword">const</span> product = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> };

    act(<span class="hljs-function">() =&gt;</span> {
      result.current.addItem(product);
    });

    expect(result.current.items).toHaveLength(<span class="hljs-number">1</span>);
    expect(result.current.items[<span class="hljs-number">0</span>]).toEqual({ ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> });
    expect(result.current.total).toBe(<span class="hljs-number">10</span>);
    expect(result.current.itemCount).toBe(<span class="hljs-number">1</span>);
  });

  test(<span class="hljs-string">'should remove item from cart'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCart());

    <span class="hljs-keyword">const</span> product = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Test Product'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> };

    <span class="hljs-comment">// Add item first</span>
    act(<span class="hljs-function">() =&gt;</span> {
      result.current.addItem(product);
    });

    <span class="hljs-comment">// Then remove it</span>
    act(<span class="hljs-function">() =&gt;</span> {
      result.current.removeItem(<span class="hljs-number">1</span>);
    });

    expect(result.current.items).toHaveLength(<span class="hljs-number">0</span>);
    expect(result.current.total).toBe(<span class="hljs-number">0</span>);
    expect(result.current.itemCount).toBe(<span class="hljs-number">0</span>);
  });

  test(<span class="hljs-string">'should handle multiple items'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCart());

    <span class="hljs-keyword">const</span> product1 = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Product 1'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> };
    <span class="hljs-keyword">const</span> product2 = { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Product 2'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">15</span> };

    act(<span class="hljs-function">() =&gt;</span> {
      result.current.addItem(product1);
      result.current.addItem(product2);
    });

    expect(result.current.items).toHaveLength(<span class="hljs-number">2</span>);
    expect(result.current.total).toBe(<span class="hljs-number">25</span>);
    expect(result.current.itemCount).toBe(<span class="hljs-number">2</span>);
  });
});
</code></pre>
<h2 id="heading-when-to-use-each-approach-a-decision-framework">When to Use Each Approach: A Decision Framework</h2>
<p>Choosing the right state management approach is crucial for maintainable applications. Here's how to decide:</p>
<h3 id="heading-decision-tree-for-state-management">Decision tree for state management</h3>
<p>1. Is the state only needed by one component and its direct children? → Use local state with useState:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good for: Form inputs, toggles, local UI state</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ContactForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);        <span class="hljs-comment">// Only this form needs it</span>
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);      <span class="hljs-comment">// Only this form needs it</span>
  <span class="hljs-keyword">const</span> [isSubmitting, setIsSubmitting] = useState(<span class="hljs-literal">false</span>); <span class="hljs-comment">// Only this form needs it</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setName(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{isSubmitting}</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p>2. Do 3-5 components need the same data, and it doesn't change frequently? → Use React Context:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good for: User authentication, theme settings, language preferences</span>
<span class="hljs-keyword">const</span> ThemeContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);  <span class="hljs-comment">// Changes rarely</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">theme</span>, <span class="hljs-attr">setTheme</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Used by Header, Sidebar, Settings components</span>
</code></pre>
<p>3. Do many unrelated components need the same data that changes frequently? → Use a state management library (Redux, Zustand):</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good for: Shopping cart, complex forms, real-time data</span>
<span class="hljs-keyword">const</span> useCartStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">items</span>: [...state.items, product],
    <span class="hljs-attr">total</span>: state.total + product.price
  }))
}));

<span class="hljs-comment">// Used by ProductCard, CartBadge, CartSidebar, Checkout, etc.</span>
</code></pre>
<p>4. Do you need to encapsulate reusable logic across multiple components? → Create custom hooks:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good for: API calls, form validation, complex calculations</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useApi</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(url)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
      .then(setData)
      .catch(setError)
      .finally(<span class="hljs-function">() =&gt;</span> setLoading(<span class="hljs-literal">false</span>));
  }, [url]);

  <span class="hljs-keyword">return</span> { data, loading, error };
}

<span class="hljs-comment">// Reusable across any component that needs API data</span>
</code></pre>
<h3 id="heading-detailed-comparison-of-approaches">Detailed comparison of approaches</h3>
<p>Here’s a helpful table that lays out each approach along with their best use cases, pros, and cons:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Approach</td><td>Best For</td><td>Pros</td><td>Cons</td><td>Learning Curve</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Local State</strong></td><td>Form inputs, UI toggles, component-specific data</td><td>Simple, fast, built-in</td><td>Limited scope, prop drilling</td><td>Easy</td></tr>
<tr>
<td><strong>Context</strong></td><td>Theme, auth, moderate shared state</td><td>No prop drilling, built-in</td><td>Can cause re-renders, not great for frequent updates</td><td>Medium</td></tr>
<tr>
<td><strong>Redux</strong></td><td>Complex state, time-travel debugging, large teams</td><td>Predictable, great DevTools, scalable</td><td>Lots of boilerplate, learning curve</td><td>Hard</td></tr>
<tr>
<td><strong>Redux Toolkit</strong></td><td>Modern Redux projects</td><td>Less boilerplate than Redux, good patterns</td><td>Still complex, opinionated</td><td>Medium-Hard</td></tr>
<tr>
<td><strong>Zustand</strong></td><td>Simple global state, modern projects</td><td>Minimal boilerplate, TypeScript friendly, small</td><td>Less ecosystem, newer library</td><td>Easy-Medium</td></tr>
<tr>
<td><strong>Custom Hooks</strong></td><td>Reusable logic, moderate complexity</td><td>Composable, reusable, testable</td><td>Can get complex, need good patterns</td><td>Medium</td></tr>
</tbody>
</table>
</div><h3 id="heading-real-world-examples-of-when-to-use-each">Real-world examples of when to use each</h3>
<h4 id="heading-local-state-examples">Local State Examples</h4>
<p>Local state excels when data is <strong>temporary, component-specific, and doesn't need to be shared</strong>. It provides the fastest performance and simplest code because there's no overhead of state management systems.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ Perfect for local state</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ImageGallery</span>(<span class="hljs-params">{ images }</span>) </span>{
  <span class="hljs-keyword">const</span> [currentIndex, setCurrentIndex] = useState(<span class="hljs-number">0</span>);    <span class="hljs-comment">// Only this component cares</span>
  <span class="hljs-keyword">const</span> [isFullscreen, setIsFullscreen] = useState(<span class="hljs-literal">false</span>); <span class="hljs-comment">// Only this component cares</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"gallery"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{images[currentIndex]}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCurrentIndex(currentIndex + 1)}&gt;Next<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsFullscreen(true)}&gt;Fullscreen<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// ✅ Good for forms</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [errors, setErrors] = useState({});

  <span class="hljs-comment">// All this state is specific to this form</span>
}
</code></pre>
<p>Local state works here because:</p>
<ul>
<li><p>State is contained within the component that uses it</p>
</li>
<li><p>No external subscriptions or providers are needed</p>
</li>
<li><p>It’s easy to reason about and test</p>
</li>
<li><p>State automatically clears when component unmounts</p>
</li>
<li><p>Component is self-contained and reusable</p>
</li>
</ul>
<h4 id="heading-context-examples">Context Examples</h4>
<p>Context works best for <strong>stable data that many components need but changes infrequently</strong>. It eliminates prop drilling while avoiding the complexity of full state management libraries.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ Perfect for Context - used by many components, changes rarely</span>
<span class="hljs-keyword">const</span> AuthContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AuthProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [isLoggedIn, setIsLoggedIn] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-comment">// Authentication status doesn't change frequently</span>
  <span class="hljs-comment">// Many components need to know if user is logged in</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AuthContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">user</span>, <span class="hljs-attr">isLoggedIn</span>, <span class="hljs-attr">setUser</span>, <span class="hljs-attr">setIsLoggedIn</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// ✅ Good for theme settings</span>
<span class="hljs-keyword">const</span> ThemeContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);
  <span class="hljs-keyword">const</span> [fontSize, setFontSize] = useState(<span class="hljs-string">'medium'</span>);

  <span class="hljs-comment">// Theme changes rarely but affects many components</span>
}
</code></pre>
<p>Context excels here because:</p>
<ul>
<li><p><strong>Wide reach, stable data</strong>: Many components need this information, but it doesn't change often</p>
</li>
<li><p><strong>Built-in solution</strong>: No external dependencies required</p>
</li>
<li><p><strong>Automatic updates</strong>: All consumers automatically re-render when the context changes</p>
</li>
<li><p><strong>Clear boundaries</strong>: Easy to understand what components have access to the data</p>
</li>
<li><p><strong>Reasonable complexity</strong>: More complex than local state but much simpler than Redux</p>
</li>
</ul>
<p>When Context struggles:</p>
<ul>
<li><p><strong>Frequent updates</strong>: Every context change causes all consumers to re-render</p>
</li>
<li><p><strong>Complex state logic</strong>: Multiple related pieces of state become unwieldy</p>
</li>
<li><p><strong>Performance critical</strong>: Large numbers of consumers can cause performance issues</p>
</li>
</ul>
<h4 id="heading-reduxzustand-examples">Redux/Zustand Examples</h4>
<p>These libraries shine when you have a <strong>complex, interconnected state that changes frequently and needs to be accessed by many unrelated components</strong>. They provide predictable updates, debugging tools, and performance optimizations.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ Perfect for Redux/Zustand - complex state, many components, frequent updates</span>
<span class="hljs-keyword">const</span> useShoppingStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-comment">// Cart data</span>
  <span class="hljs-attr">cart</span>: { <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> },

  <span class="hljs-comment">// User data  </span>
  <span class="hljs-attr">user</span>: { <span class="hljs-attr">profile</span>: <span class="hljs-literal">null</span>, <span class="hljs-attr">preferences</span>: {} },

  <span class="hljs-comment">// UI state</span>
  <span class="hljs-attr">ui</span>: { 
    <span class="hljs-attr">sidebarOpen</span>: <span class="hljs-literal">false</span>, 
    <span class="hljs-attr">currentPage</span>: <span class="hljs-string">'home'</span>,
    <span class="hljs-attr">notifications</span>: []
  },

  <span class="hljs-comment">// Many actions that update different parts of state</span>
  <span class="hljs-attr">addToCart</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">cart</span>: {
      <span class="hljs-attr">items</span>: [...state.cart.items, product],
      <span class="hljs-attr">total</span>: state.cart.total + product.price
    }
  })),

  <span class="hljs-attr">updateUserProfile</span>: <span class="hljs-function">(<span class="hljs-params">profile</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">user</span>: { ...state.user, profile }
  })),

  <span class="hljs-attr">showNotification</span>: <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">ui</span>: {
      ...state.ui,
      <span class="hljs-attr">notifications</span>: [...state.ui.notifications, { <span class="hljs-attr">id</span>: <span class="hljs-built_in">Date</span>.now(), message }]
    }
  }))
}));

<span class="hljs-comment">// Used by: ProductCard, CartBadge, UserProfile, Sidebar, Notifications, etc.</span>
</code></pre>
<p>Why state management libraries excel here:</p>
<ul>
<li><p><strong>Centralized logic</strong>: All state changes go through predictable update mechanisms</p>
</li>
<li><p><strong>Performance optimization</strong>: Libraries provide selector-based subscriptions to minimize re-renders</p>
</li>
<li><p><strong>Debugging tools</strong>: Redux DevTools, time-travel debugging, action tracking</p>
</li>
<li><p><strong>Scalability</strong>: Can handle complex state relationships and async operations</p>
</li>
<li><p><strong>Team consistency</strong>: Established patterns that multiple developers can follow</p>
</li>
<li><p><strong>Middleware support</strong>: Logging, persistence, error handling can be added systematically</p>
</li>
</ul>
<p><strong>Redux</strong> is best for large teams, complex async flows, need for strict predictability. <strong>Zustand</strong> is best for modern apps that want Redux benefits without boilerplate. And <strong>Recoil/Jotai</strong> is best for fine-grained reactive updates and complex dependencies.</p>
<h4 id="heading-custom-hook-examples">Custom Hook Examples</h4>
<p>Custom hooks excel when you have <strong>stateful logic that multiple components need, but the logic itself is more important than the data</strong>. They provide composition and reusability while keeping complexity contained.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ Perfect for custom hooks - reusable logic</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useLocalStorage</span>(<span class="hljs-params">key, initialValue</span>) </span>{
  <span class="hljs-keyword">const</span> [storedValue, setStoredValue] = useState(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> item = <span class="hljs-built_in">window</span>.localStorage.getItem(key);
      <span class="hljs-keyword">return</span> item ? <span class="hljs-built_in">JSON</span>.parse(item) : initialValue;
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">return</span> initialValue;
    }
  });

  <span class="hljs-keyword">const</span> setValue = <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> {
    <span class="hljs-keyword">try</span> {
      setStoredValue(value);
      <span class="hljs-built_in">window</span>.localStorage.setItem(key, <span class="hljs-built_in">JSON</span>.stringify(value));
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error saving to localStorage:'</span>, error);
    }
  };

  <span class="hljs-keyword">return</span> [storedValue, setValue];
}

<span class="hljs-comment">// ✅ Reusable API logic</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useApi</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> cancelled = <span class="hljs-literal">false</span>;

    fetch(url)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (!response.ok) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network response was not ok'</span>);
        <span class="hljs-keyword">return</span> response.json();
      })
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (!cancelled) {
          setData(data);
          setLoading(<span class="hljs-literal">false</span>);
        }
      })
      .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (!cancelled) {
          setError(error);
          setLoading(<span class="hljs-literal">false</span>);
        }
      });

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> { cancelled = <span class="hljs-literal">true</span>; };
  }, [url]);

  <span class="hljs-keyword">return</span> { data, loading, error };
}

<span class="hljs-comment">// Can be used in any component that needs API data</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProfile</span>(<span class="hljs-params">{ userId }</span>) </span>{
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: user, loading, error } = useApi(<span class="hljs-string">`/api/users/<span class="hljs-subst">${userId}</span>`</span>);

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Welcome, {user.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}
</code></pre>
<p>Why custom hooks are perfect here:</p>
<ul>
<li><p><strong>Logic reusability</strong>: Same stateful behavior can be used across multiple components</p>
</li>
<li><p><strong>Composition</strong>: Hooks can be combined and built upon each other</p>
</li>
<li><p><strong>Separation of concerns</strong>: Business logic is separated from UI rendering</p>
</li>
<li><p><strong>Testability</strong>: Logic can be tested independently of components</p>
</li>
<li><p><strong>Flexibility</strong>: Each component can use the hook differently while sharing core logic</p>
</li>
<li><p><strong>No provider overhead</strong>: Unlike Context, no wrapper components needed</p>
</li>
</ul>
<p>When custom hooks work best:</p>
<ul>
<li><p><strong>Cross-cutting concerns</strong>: Authentication, API calls, form validation, local storage</p>
</li>
<li><p><strong>Complex calculations</strong>: Data processing that multiple components need</p>
</li>
<li><p><strong>Third-party integrations</strong>: Wrapping external libraries with React-friendly interfaces</p>
</li>
<li><p><strong>Stateful behavior</strong>: Managing complex state machines or multi-step processes</p>
</li>
</ul>
<h2 id="heading-common-pitfalls-and-how-to-avoid-them">Common Pitfalls and How to Avoid Them</h2>
<p>Understanding common mistakes helps you write better, more maintainable code.</p>
<h3 id="heading-pitfall-1-context-hell-too-many-nested-providers">Pitfall 1: Context hell (too many nested providers)</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Too many nested providers make code hard to read and maintain</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">CartProvider</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">NotificationProvider</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">AnalyticsProvider</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">FeatureFlagProvider</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">LocaleProvider</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span> /&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">LocaleProvider</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">FeatureFlagProvider</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">AnalyticsProvider</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">NotificationProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">CartProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserProvider</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Why this is bad:</strong></p>
<ul>
<li><p>Hard to read and understand the component hierarchy</p>
</li>
<li><p>Difficult to reorder or remove providers</p>
</li>
<li><p>Each level of nesting adds complexity</p>
</li>
<li><p>Testing becomes difficult with so many providers</p>
</li>
</ul>
<p><strong>Solution 1: Combine related providers</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ BETTER: Group related providers together</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AppProviders</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">LocaleProvider</span>&gt;</span>
          {children}
        <span class="hljs-tag">&lt;/<span class="hljs-name">LocaleProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserProvider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ShoppingProviders</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">NotificationProvider</span>&gt;</span>
        {children}
      <span class="hljs-tag">&lt;/<span class="hljs-name">NotificationProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartProvider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppProviders</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ShoppingProviders</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ShoppingProviders</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppProviders</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Solution 2: Use a state management library instead</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ EVEN BETTER: Use Zustand or Redux for complex state</span>
<span class="hljs-keyword">const</span> useAppStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>,
  <span class="hljs-attr">cart</span>: { <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">notifications</span>: [],

  <span class="hljs-comment">// All actions in one place</span>
  <span class="hljs-attr">setUser</span>: <span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> set({ user }),
  <span class="hljs-attr">setTheme</span>: <span class="hljs-function">(<span class="hljs-params">theme</span>) =&gt;</span> set({ theme }),
  <span class="hljs-attr">addToCart</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">cart</span>: {
      <span class="hljs-attr">items</span>: [...state.cart.items, product],
      <span class="hljs-attr">total</span>: state.cart.total + product.price
    }
  })),
  <span class="hljs-attr">addNotification</span>: <span class="hljs-function">(<span class="hljs-params">notification</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">notifications</span>: [...state.notifications, notification]
  }))
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// No providers needed! Just use the store directly</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-pitfall-2-massive-context-values-causing-unnecessary-re-renders">Pitfall 2: Massive context values causing unnecessary re-renders</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Putting everything in one context causes all components to re-render</span>
<span class="hljs-keyword">const</span> AppContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AppProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [cart, setCart] = useState({ <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> });
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);
  <span class="hljs-keyword">const</span> [notifications, setNotifications] = useState([]);
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([]);
  <span class="hljs-keyword">const</span> [orders, setOrders] = useState([]);
  <span class="hljs-comment">// ... 15 more pieces of state</span>

  <span class="hljs-comment">// Every time ANY state changes, ALL components re-render!</span>
  <span class="hljs-keyword">const</span> value = {
    user, setUser,
    cart, setCart,
    theme, setTheme,
    notifications, setNotifications,
    products, setProducts,
    orders, setOrders,
    <span class="hljs-comment">// ... and all the rest</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// This component only needs theme, but re-renders when user, cart, etc. change</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeToggle</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme, setTheme } = useContext(AppContext);  <span class="hljs-comment">// Gets ALL context data</span>

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'ThemeToggle rendering'</span>);  <span class="hljs-comment">// This logs way too often!</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTheme(theme === 'light' ? 'dark' : 'light')}&gt;
      Theme: {theme}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Why this is bad:</strong></p>
<ul>
<li><p>Components re-render when unrelated state changes</p>
</li>
<li><p>Poor performance as your app grows</p>
</li>
<li><p>Hard to debug which state changes cause which re-renders</p>
</li>
<li><p>Difficult to optimize individual pieces of state</p>
</li>
</ul>
<p><strong>Solution: Separate contexts by domain</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ BETTER: Separate contexts for different domains</span>
<span class="hljs-keyword">const</span> UserContext = createContext();
<span class="hljs-keyword">const</span> CartContext = createContext();  
<span class="hljs-keyword">const</span> ThemeContext = createContext();
<span class="hljs-keyword">const</span> NotificationContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [isAuthenticated, setIsAuthenticated] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-comment">// Only user-related state here</span>
  <span class="hljs-keyword">const</span> value = useMemo(<span class="hljs-function">() =&gt;</span> ({
    user, 
    setUser, 
    isAuthenticated, 
    setIsAuthenticated
  }), [user, isAuthenticated]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);
  <span class="hljs-keyword">const</span> [fontSize, setFontSize] = useState(<span class="hljs-string">'medium'</span>);

  <span class="hljs-comment">// Only theme-related state here</span>
  <span class="hljs-keyword">const</span> value = useMemo(<span class="hljs-function">() =&gt;</span> ({
    theme, 
    setTheme, 
    fontSize, 
    setFontSize
  }), [theme, fontSize]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Now ThemeToggle only re-renders when theme changes</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeToggle</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme, setTheme } = useContext(ThemeContext);  <span class="hljs-comment">// Only theme data</span>

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'ThemeToggle rendering'</span>);  <span class="hljs-comment">// Only logs when theme changes</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTheme(theme === 'light' ? 'dark' : 'light')}&gt;
      Theme: {theme}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-pitfall-3-not-memoizing-context-values">Pitfall 3: Not memoizing context values</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Creates new objects every render</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
      // <span class="hljs-attr">This</span> <span class="hljs-attr">creates</span> <span class="hljs-attr">a</span> <span class="hljs-attr">NEW</span> <span class="hljs-attr">object</span> <span class="hljs-attr">every</span> <span class="hljs-attr">time</span> <span class="hljs-attr">CartProvider</span> <span class="hljs-attr">renders</span>!
      <span class="hljs-attr">items</span>,                      // <span class="hljs-attr">Same</span> <span class="hljs-attr">data</span> <span class="hljs-attr">but</span> <span class="hljs-attr">new</span> <span class="hljs-attr">object</span> <span class="hljs-attr">reference</span>
      <span class="hljs-attr">total</span>,                      // <span class="hljs-attr">Same</span> <span class="hljs-attr">data</span> <span class="hljs-attr">but</span> <span class="hljs-attr">new</span> <span class="hljs-attr">object</span> <span class="hljs-attr">reference</span>
      <span class="hljs-attr">addItem:</span> (<span class="hljs-attr">item</span>) =&gt;</span> {        // NEW function every render!
        setItems([...items, item]);
      },
      removeItem: (id) =&gt; {       // NEW function every render!
        setItems(items.filter(item =&gt; item.id !== id));
      }
    }}&gt;
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Why this is bad:</strong></p>
<ul>
<li><p>React uses <code>Object.is()</code> to compare context values</p>
</li>
<li><p>Even if data is the same, new objects cause all consumers to re-render</p>
</li>
<li><p>New functions break optimization in child components</p>
</li>
<li><p>Performance degrades as more components use the context</p>
</li>
</ul>
<p><strong>Solution: Memoize context values and functions</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ CORRECT: Memoize the context value and functions</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-comment">// useCallback memoizes functions - they only change when dependencies change</span>
  <span class="hljs-keyword">const</span> addItem = useCallback(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prevItems</span> =&gt;</span> [...prevItems, item]);  <span class="hljs-comment">// Use function update to avoid dependency</span>
  }, []);  <span class="hljs-comment">// Empty deps = function never changes</span>

  <span class="hljs-keyword">const</span> removeItem = useCallback(<span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prevItems</span> =&gt;</span> prevItems.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== id));
  }, []);

  <span class="hljs-keyword">const</span> updateQuantity = useCallback(<span class="hljs-function">(<span class="hljs-params">id, quantity</span>) =&gt;</span> {
    setItems(<span class="hljs-function"><span class="hljs-params">prevItems</span> =&gt;</span> 
      prevItems.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> 
        item.id === id ? { ...item, quantity } : item
      )
    );
  }, []);

  <span class="hljs-comment">// useMemo memoizes the context value object</span>
  <span class="hljs-keyword">const</span> value = useMemo(<span class="hljs-function">() =&gt;</span> ({
    items,
    total,
    addItem,
    removeItem,
    updateQuantity,
    <span class="hljs-attr">itemCount</span>: items.length  <span class="hljs-comment">// Computed value</span>
  }), [items, total, addItem, removeItem, updateQuantity]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CartContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">CartContext.Provider</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>What useCallback and useMemo do:</strong></p>
<ul>
<li><p><strong>useCallback(fn, deps)</strong> returns the same function reference until dependencies change</p>
</li>
<li><p><strong>useMemo(fn, deps)</strong> returns the same value until dependencies change</p>
</li>
<li><p><strong>Why this matters</strong>: React components only re-render when their props change by reference</p>
</li>
</ul>
<h3 id="heading-pitfall-4-prop-drilling-when-context-would-be-better">Pitfall 4: Prop drilling when Context would be better</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Passing user data through many components that don't use it</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'admin'</span> });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">user</span>=<span class="hljs-string">{user}</span> /&gt;</span>  {/* Header doesn't use user, just passes it down */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ user }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Logo</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Navigation</span> <span class="hljs-attr">user</span>=<span class="hljs-string">{user}</span> /&gt;</span>  {/* Navigation doesn't use user either */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Navigation</span>(<span class="hljs-params">{ user }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/products"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UserMenu</span> <span class="hljs-attr">user</span>=<span class="hljs-string">{user}</span> /&gt;</span>  {/* Finally! Someone who uses user */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserMenu</span>(<span class="hljs-params">{ user }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-menu"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Welcome, {user.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>  {/* This is where user is actually used */}
      {user.role === 'admin' &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/admin"</span>&gt;</span>Admin Panel<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Why this is problematic:</strong></p>
<ul>
<li><p>Header and Navigation don't care about user but must know about it</p>
</li>
<li><p>Adding new user data requires updating multiple components</p>
</li>
<li><p>Components become tightly coupled</p>
</li>
<li><p>Testing becomes complex because you need to mock props that components don't use</p>
</li>
</ul>
<p><strong>Solution: Use Context for data that skips intermediate components</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ BETTER: Use Context for data that needs to skip levels</span>
<span class="hljs-keyword">const</span> UserContext = createContext();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserProvider</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'admin'</span> });

  <span class="hljs-keyword">const</span> value = useMemo(<span class="hljs-function">() =&gt;</span> ({ user, setUser }), [user]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> context = useContext(UserContext);
  <span class="hljs-keyword">if</span> (!context) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useUser must be used within UserProvider'</span>);
  }
  <span class="hljs-keyword">return</span> context;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>  {/* No props needed! */}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">UserProvider</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Logo</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Navigation</span> /&gt;</span>  {/* No props needed! */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Navigation</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/products"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UserMenu</span> /&gt;</span>  {/* No props needed! */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserMenu</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { user } = useUser();  <span class="hljs-comment">// Gets user data directly from context</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-menu"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Welcome, {user.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      {user.role === 'admin' &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/admin"</span>&gt;</span>Admin Panel<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-pitfall-5-using-global-state-for-everything">Pitfall 5: Using global state for everything</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Putting local UI state in global store</span>
<span class="hljs-keyword">const</span> useAppStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-comment">// Global state (good)</span>
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">cart</span>: { <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>,

  <span class="hljs-comment">// Local UI state (bad - should be local to component)</span>
  <span class="hljs-attr">loginModalOpen</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">searchQuery</span>: <span class="hljs-string">''</span>,
  <span class="hljs-attr">currentPage</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">sortDirection</span>: <span class="hljs-string">'asc'</span>,
  <span class="hljs-attr">selectedFilters</span>: [],

  <span class="hljs-comment">// Actions for everything</span>
  <span class="hljs-attr">setLoginModalOpen</span>: <span class="hljs-function">(<span class="hljs-params">open</span>) =&gt;</span> set({ <span class="hljs-attr">loginModalOpen</span>: open }),
  <span class="hljs-attr">setSearchQuery</span>: <span class="hljs-function">(<span class="hljs-params">query</span>) =&gt;</span> set({ <span class="hljs-attr">searchQuery</span>: query }),
  <span class="hljs-attr">setCurrentPage</span>: <span class="hljs-function">(<span class="hljs-params">page</span>) =&gt;</span> set({ <span class="hljs-attr">currentPage</span>: page }),
  <span class="hljs-comment">// ... many more actions</span>
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SearchBox</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { searchQuery, setSearchQuery } = useAppStore();

  <span class="hljs-comment">// This causes ALL components using the store to re-render when user types!</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
      <span class="hljs-attr">value</span>=<span class="hljs-string">{searchQuery}</span> 
      <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setSearchQuery(e.target.value)} 
    /&gt;</span>
  );
}
</code></pre>
<p><strong>Why this is bad:</strong></p>
<ul>
<li><p>Every keystroke causes all store consumers to re-render</p>
</li>
<li><p>Store becomes cluttered with temporary UI state</p>
</li>
<li><p>Hard to reset state when component unmounts</p>
</li>
<li><p>Increases coupling between unrelated components</p>
</li>
</ul>
<p><strong>Solution: Keep local state local, global state global</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ BETTER: Separate local and global concerns</span>
<span class="hljs-keyword">const</span> useAppStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-comment">// Only truly global state</span>
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">cart</span>: { <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>,

  <span class="hljs-comment">// Actions for global state only</span>
  <span class="hljs-attr">setUser</span>: <span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> set({ user }),
  <span class="hljs-attr">addToCart</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">cart</span>: {
      <span class="hljs-attr">items</span>: [...state.cart.items, product],
      <span class="hljs-attr">total</span>: state.cart.total + product.price
    }
  })),
  <span class="hljs-attr">setTheme</span>: <span class="hljs-function">(<span class="hljs-params">theme</span>) =&gt;</span> set({ theme })
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SearchBox</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Local state for local concerns</span>
  <span class="hljs-keyword">const</span> [searchQuery, setSearchQuery] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [isSearching, setIsSearching] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> handleSearch = <span class="hljs-keyword">async</span> () =&gt; {
    setIsSearching(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> searchAPI(searchQuery);
      <span class="hljs-comment">// Handle results...</span>
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// Handle error...</span>
    } <span class="hljs-keyword">finally</span> {
      setIsSearching(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
        <span class="hljs-attr">value</span>=<span class="hljs-string">{searchQuery}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setSearchQuery(e.target.value)}  // No global re-renders!
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSearch}</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{isSearching}</span>&gt;</span>
        {isSearching ? 'Searching...' : 'Search'}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LoginModal</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Modal open/closed state is local to this component</span>
  <span class="hljs-keyword">const</span> [isOpen, setIsOpen] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(true)}&gt;Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      {isOpen &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span> <span class="hljs-attr">onClose</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(false)}&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">LoginForm</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p><strong>Guidelines for what belongs where:</strong></p>
<ul>
<li><p><strong>Local state</strong>: Form inputs, modal open/closed, loading states, temporary UI state</p>
</li>
<li><p><strong>Global state</strong>: User authentication, shopping cart, theme, data shared across pages</p>
</li>
</ul>
<h3 id="heading-pitfall-6-not-handling-loading-and-error-states-in-shared-state">Pitfall 6: Not handling loading and error states in shared state</h3>
<p><strong>The Problem:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ❌ WRONG: Not handling async operations properly</span>
<span class="hljs-keyword">const</span> useUserStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,

  <span class="hljs-comment">// Missing loading and error states!</span>
  <span class="hljs-attr">login</span>: <span class="hljs-keyword">async</span> (email, password) =&gt; {
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> authAPI.login(email, password);  <span class="hljs-comment">// What if this fails?</span>
    set({ user });
  }
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { login } = useUserStore();
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();
    <span class="hljs-keyword">await</span> login(email, password);  <span class="hljs-comment">// No way to show loading or handle errors</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setPassword(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>  {/* No loading state */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Solution: Always include loading and error states</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ BETTER: Handle async operations properly</span>
<span class="hljs-keyword">const</span> useUserStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,

  <span class="hljs-attr">login</span>: <span class="hljs-keyword">async</span> (email, password) =&gt; {
    set({ <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });  <span class="hljs-comment">// Start loading, clear previous errors</span>

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> authAPI.login(email, password);
      set({ user, <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });  <span class="hljs-comment">// Success</span>
    } <span class="hljs-keyword">catch</span> (error) {
      set({ 
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>, 
        <span class="hljs-attr">error</span>: error.message || <span class="hljs-string">'Login failed'</span>,  <span class="hljs-comment">// Store error message</span>
        <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span> 
      });
    }
  },

  <span class="hljs-attr">logout</span>: <span class="hljs-function">() =&gt;</span> {
    set({ <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });  <span class="hljs-comment">// Clear user and any errors</span>
  },

  <span class="hljs-attr">clearError</span>: <span class="hljs-function">() =&gt;</span> {
    set({ <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });  <span class="hljs-comment">// Allow manual error clearing</span>
  }
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { login, loading, error, clearError } = useUserStore();
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();
    clearError();  <span class="hljs-comment">// Clear any previous errors</span>
    <span class="hljs-keyword">await</span> login(email, password);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      {error &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"error-message"</span>&gt;</span>
          {error}
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{clearError}</span>&gt;</span>×<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
        <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> 
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)}
        disabled={loading}  // Disable during loading
      /&gt;

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
        <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span> 
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setPassword(e.target.value)}
        disabled={loading}  // Disable during loading
      /&gt;

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{loading}</span>&gt;</span>
        {loading ? 'Logging in...' : 'Login'}  {/* Show loading state */}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-best-practices-for-maintainable-shared-state">Best Practices for Maintainable Shared State</h2>
<p>Following established patterns makes your code easier to understand and maintain.</p>
<h3 id="heading-1-use-consistent-naming-conventions">1. Use consistent naming conventions</h3>
<p>Be descriptive and consistent with your naming:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ GOOD: Clear, descriptive names</span>
<span class="hljs-keyword">const</span> useCartStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-comment">// State names are clear</span>
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">totalPrice</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,

  <span class="hljs-comment">// Action names describe what they do</span>
  <span class="hljs-attr">addItemToCart</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
    <span class="hljs-attr">items</span>: [...state.items, { ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
    <span class="hljs-attr">totalPrice</span>: state.totalPrice + product.price,
    <span class="hljs-attr">itemCount</span>: state.itemCount + <span class="hljs-number">1</span>
  })),

  <span class="hljs-attr">removeItemFromCart</span>: <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> itemToRemove = state.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);
    <span class="hljs-keyword">if</span> (!itemToRemove) <span class="hljs-keyword">return</span> state;

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">items</span>: state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),
      <span class="hljs-attr">totalPrice</span>: state.totalPrice - (itemToRemove.price * itemToRemove.quantity),
      <span class="hljs-attr">itemCount</span>: state.itemCount - itemToRemove.quantity
    };
  }),

  <span class="hljs-attr">clearCart</span>: <span class="hljs-function">() =&gt;</span> set({
    <span class="hljs-attr">items</span>: [],
    <span class="hljs-attr">totalPrice</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">itemCount</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
  })
}));

<span class="hljs-comment">// ❌ BAD: Unclear, inconsistent names</span>
<span class="hljs-keyword">const</span> useStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-comment">// Unclear what these are</span>
  <span class="hljs-attr">data</span>: [],
  <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">err</span>: <span class="hljs-literal">null</span>,

  <span class="hljs-comment">// Unclear what these do</span>
  <span class="hljs-attr">add</span>: <span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">s</span>) =&gt;</span> ({ <span class="hljs-attr">data</span>: [...s.data, x] })),
  <span class="hljs-attr">remove</span>: <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">s</span>) =&gt;</span> ({ <span class="hljs-attr">data</span>: s.data.filter(<span class="hljs-function"><span class="hljs-params">i</span> =&gt;</span> i.id !== id) })),
  <span class="hljs-attr">clear</span>: <span class="hljs-function">() =&gt;</span> set({ <span class="hljs-attr">data</span>: [], <span class="hljs-attr">num</span>: <span class="hljs-number">0</span> })
}));
</code></pre>
<h3 id="heading-2-group-related-state-and-actions-together">2. Group related state and actions together</h3>
<p>Organize your state by feature, not by type:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ GOOD: Organized by feature domains</span>
<span class="hljs-keyword">const</span> useAppStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-comment">// User-related state</span>
  <span class="hljs-attr">user</span>: {
    <span class="hljs-attr">profile</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">preferences</span>: {},
    <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
  },

  <span class="hljs-comment">// Cart-related state</span>
  <span class="hljs-attr">cart</span>: {
    <span class="hljs-attr">items</span>: [],
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">discount</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
  },

  <span class="hljs-comment">// UI-related state</span>
  <span class="hljs-attr">ui</span>: {
    <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>,
    <span class="hljs-attr">sidebarOpen</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">currentPage</span>: <span class="hljs-string">'home'</span>,
    <span class="hljs-attr">notifications</span>: []
  },

  <span class="hljs-comment">// User actions</span>
  <span class="hljs-attr">userActions</span>: {
    <span class="hljs-attr">login</span>: <span class="hljs-keyword">async</span> (credentials) =&gt; {
      set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
        <span class="hljs-attr">user</span>: { ...state.user, <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> }
      }));

      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> profile = <span class="hljs-keyword">await</span> authAPI.login(credentials);
        set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
          <span class="hljs-attr">user</span>: {
            ...state.user,
            profile,
            <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>
          }
        }));
      } <span class="hljs-keyword">catch</span> (error) {
        set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
          <span class="hljs-attr">user</span>: {
            ...state.user,
            <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">error</span>: error.message
          }
        }));
      }
    },

    <span class="hljs-attr">logout</span>: <span class="hljs-function">() =&gt;</span> {
      set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
        <span class="hljs-attr">user</span>: {
          <span class="hljs-attr">profile</span>: <span class="hljs-literal">null</span>,
          <span class="hljs-attr">preferences</span>: {},
          <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
        }
      }));
    }
  },

  <span class="hljs-comment">// Cart actions</span>
  <span class="hljs-attr">cartActions</span>: {
    <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
      <span class="hljs-attr">cart</span>: {
        ...state.cart,
        <span class="hljs-attr">items</span>: [...state.cart.items, { ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }],
        <span class="hljs-attr">total</span>: state.cart.total + product.price
      }
    })),

    <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> state = get();
      <span class="hljs-keyword">const</span> item = state.cart.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

      <span class="hljs-keyword">if</span> (item) {
        set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
          <span class="hljs-attr">cart</span>: {
            ...state.cart,
            <span class="hljs-attr">items</span>: state.cart.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),
            <span class="hljs-attr">total</span>: state.cart.total - (item.price * item.quantity)
          }
        }));
      }
    }
  },

  <span class="hljs-comment">// UI actions</span>
  <span class="hljs-attr">uiActions</span>: {
    <span class="hljs-attr">setTheme</span>: <span class="hljs-function">(<span class="hljs-params">theme</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
      <span class="hljs-attr">ui</span>: { ...state.ui, theme }
    })),

    <span class="hljs-attr">toggleSidebar</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
      <span class="hljs-attr">ui</span>: { ...state.ui, <span class="hljs-attr">sidebarOpen</span>: !state.ui.sidebarOpen }
    })),

    <span class="hljs-attr">addNotification</span>: <span class="hljs-function">(<span class="hljs-params">notification</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
      <span class="hljs-attr">ui</span>: {
        ...state.ui,
        <span class="hljs-attr">notifications</span>: [...state.ui.notifications, {
          <span class="hljs-attr">id</span>: <span class="hljs-built_in">Date</span>.now(),
          ...notification
        }]
      }
    }))
  }
}));

<span class="hljs-comment">// Usage is clean and organized</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductCard</span>(<span class="hljs-params">{ product }</span>) </span>{
  <span class="hljs-keyword">const</span> addItem = useAppStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.cartActions.addItem);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{product.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addItem(product)}&gt;
        Add to Cart
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-3-create-selector-hooks-for-complex-data-access">3. Create selector hooks for complex data access</h3>
<p>Make data access predictable and reusable:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ GOOD: Dedicated selector hooks</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCartSelectors</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> items = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.items);
  <span class="hljs-keyword">const</span> totalPrice = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.totalPrice);
  <span class="hljs-keyword">const</span> itemCount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.itemCount);
  <span class="hljs-keyword">const</span> isLoading = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.isLoading);
  <span class="hljs-keyword">const</span> error = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.error);

  <span class="hljs-comment">// Computed values</span>
  <span class="hljs-keyword">const</span> isEmpty = itemCount === <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> hasDiscount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.discount &gt; <span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> finalTotal = totalPrice - useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.discount);

  <span class="hljs-keyword">return</span> {
    items,
    totalPrice,
    itemCount,
    isLoading,
    error,
    isEmpty,
    hasDiscount,
    finalTotal
  };
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCartActions</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> addItem = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.addItemToCart);
  <span class="hljs-keyword">const</span> removeItem = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.removeItemFromCart);
  <span class="hljs-keyword">const</span> updateQuantity = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.updateItemQuantity);
  <span class="hljs-keyword">const</span> clearCart = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.clearCart);
  <span class="hljs-keyword">const</span> applyDiscount = useCartStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.applyDiscount);

  <span class="hljs-keyword">return</span> {
    addItem,
    removeItem,
    updateQuantity,
    clearCart,
    applyDiscount
  };
}

<span class="hljs-comment">// Clean component usage</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CartSummary</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { items, finalTotal, isEmpty, isLoading } = useCartSelectors();
  <span class="hljs-keyword">const</span> { removeItem, clearCart } = useCartActions();

  <span class="hljs-keyword">if</span> (isLoading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading cart...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (isEmpty) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Your cart is empty<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-summary"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Cart Summary<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Total: ${finalTotal.toFixed(2)}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      {items.map(item =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart-item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name} x {item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeItem(item.id)}&gt;Remove<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{clearCart}</span>&gt;</span>Clear Cart<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-4-handle-side-effects-properly">4. Handle side effects properly</h3>
<p>Separate side effects from state updates:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ GOOD: Proper side effect handling</span>
<span class="hljs-keyword">const</span> useCartStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">totalPrice</span>: <span class="hljs-number">0</span>,

  <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> {
    <span class="hljs-comment">// Update state</span>
    set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> newItems = [...state.items, { ...product, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> }];
      <span class="hljs-keyword">const</span> newTotal = state.totalPrice + product.price;

      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">items</span>: newItems,
        <span class="hljs-attr">totalPrice</span>: newTotal
      };
    });

    <span class="hljs-comment">// Handle side effects AFTER state update</span>
    <span class="hljs-keyword">const</span> newState = get();

    <span class="hljs-comment">// Analytics tracking</span>
    analytics.track(<span class="hljs-string">'Item Added to Cart'</span>, {
      <span class="hljs-attr">productId</span>: product.id,
      <span class="hljs-attr">productName</span>: product.name,
      <span class="hljs-attr">cartTotal</span>: newState.totalPrice,
      <span class="hljs-attr">itemCount</span>: newState.items.length
    });

    <span class="hljs-comment">// Save to localStorage</span>
    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'cart'</span>, <span class="hljs-built_in">JSON</span>.stringify({
      <span class="hljs-attr">items</span>: newState.items,
      <span class="hljs-attr">totalPrice</span>: newState.totalPrice
    }));

    <span class="hljs-comment">// Show notification</span>
    toast.success(<span class="hljs-string">`<span class="hljs-subst">${product.name}</span> added to cart!`</span>);

    <span class="hljs-comment">// Update browser tab title</span>
    <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`Shopping (<span class="hljs-subst">${newState.items.length}</span>) - MyStore`</span>;
  },

  <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">productId</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> currentState = get();
    <span class="hljs-keyword">const</span> itemToRemove = currentState.items.find(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === productId);

    <span class="hljs-keyword">if</span> (!itemToRemove) <span class="hljs-keyword">return</span>;

    <span class="hljs-comment">// Update state</span>
    set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
      <span class="hljs-attr">items</span>: state.items.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id !== productId),
      <span class="hljs-attr">totalPrice</span>: state.totalPrice - (itemToRemove.price * itemToRemove.quantity)
    }));

    <span class="hljs-comment">// Side effects</span>
    <span class="hljs-keyword">const</span> newState = get();

    analytics.track(<span class="hljs-string">'Item Removed from Cart'</span>, {
      <span class="hljs-attr">productId</span>: itemToRemove.id,
      <span class="hljs-attr">productName</span>: itemToRemove.name,
      <span class="hljs-attr">cartTotal</span>: newState.totalPrice
    });

    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'cart'</span>, <span class="hljs-built_in">JSON</span>.stringify({
      <span class="hljs-attr">items</span>: newState.items,
      <span class="hljs-attr">totalPrice</span>: newState.totalPrice
    }));

    toast.info(<span class="hljs-string">`<span class="hljs-subst">${itemToRemove.name}</span> removed from cart`</span>);

    <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`Shopping (<span class="hljs-subst">${newState.items.length}</span>) - MyStore`</span>;
  }
}));
</code></pre>
<h3 id="heading-5-implement-proper-error-boundaries">5. Implement proper error boundaries</h3>
<p>Handle errors gracefully at the state level:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ✅ GOOD: Comprehensive error handling</span>
<span class="hljs-keyword">const</span> useApiStore = create(<span class="hljs-function">(<span class="hljs-params">set, get</span>) =&gt;</span> ({
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">retryCount</span>: <span class="hljs-number">0</span>,

  <span class="hljs-attr">fetchData</span>: <span class="hljs-keyword">async</span> (url, options = {}) =&gt; {
    <span class="hljs-keyword">const</span> { maxRetries = <span class="hljs-number">3</span>, retryDelay = <span class="hljs-number">1000</span> } = options;

    set({ <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });

    <span class="hljs-keyword">const</span> attemptFetch = <span class="hljs-keyword">async</span> (attempt) =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url);

        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP <span class="hljs-subst">${response.status}</span>: <span class="hljs-subst">${response.statusText}</span>`</span>);
        }

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();

        set({ 
          data, 
          <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>, 
          <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
          <span class="hljs-attr">retryCount</span>: <span class="hljs-number">0</span> 
        });

      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Fetch attempt <span class="hljs-subst">${attempt}</span> failed:`</span>, error);

        <span class="hljs-keyword">if</span> (attempt &lt; maxRetries) {
          <span class="hljs-comment">// Retry with exponential backoff</span>
          <span class="hljs-keyword">const</span> delay = retryDelay * <span class="hljs-built_in">Math</span>.pow(<span class="hljs-number">2</span>, attempt - <span class="hljs-number">1</span>);
          <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> attemptFetch(attempt + <span class="hljs-number">1</span>), delay);

          set({ <span class="hljs-attr">retryCount</span>: attempt });
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// Final failure</span>
          set({ 
            <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>, 
            <span class="hljs-attr">error</span>: {
              <span class="hljs-attr">message</span>: error.message,
              <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_ERROR'</span>,
              <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString(),
              url,
              <span class="hljs-attr">attempts</span>: attempt
            },
            <span class="hljs-attr">retryCount</span>: <span class="hljs-number">0</span>
          });
        }
      }
    };

    <span class="hljs-keyword">await</span> attemptFetch(<span class="hljs-number">1</span>);
  },

  <span class="hljs-attr">retry</span>: <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> state = get();
    <span class="hljs-keyword">if</span> (state.error &amp;&amp; state.error.url) {
      state.fetchData(state.error.url);
    }
  },

  <span class="hljs-attr">clearError</span>: <span class="hljs-function">() =&gt;</span> {
    set({ <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });
  }
}));

<span class="hljs-comment">// Error boundary component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApiErrorBoundary</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">hasError</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
  }

  <span class="hljs-keyword">static</span> getDerivedStateFromError(error) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">hasError</span>: <span class="hljs-literal">true</span>, error };
  }

  componentDidCatch(error, errorInfo) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'API Error Boundary caught an error:'</span>, error, errorInfo);

    <span class="hljs-comment">// Report to error tracking service</span>
    errorTracking.report(error, {
      <span class="hljs-attr">componentStack</span>: errorInfo.componentStack,
      <span class="hljs-attr">context</span>: <span class="hljs-string">'ApiErrorBoundary'</span>
    });
  }

  render() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.state.hasError) {
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"error-fallback"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Something went wrong<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>We're sorry, but something unexpected happened.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> this.setState({ hasError: false, error: null })}&gt;
            Try Again
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.props.children;
  }
}

<span class="hljs-comment">// Usage with error handling</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DataDisplay</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { data, loading, error, retry } = useApiStore();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    useApiStore.getState().fetchData(<span class="hljs-string">'/api/data'</span>);
  }, []);

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">if</span> (error) {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"error-state"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Failed to load data<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Attempted {error.attempts} times<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{retry}</span>&gt;</span>Retry<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {data &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span>{JSON.stringify(data, null, 2)}<span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ApiErrorBoundary</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DataDisplay</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ApiErrorBoundary</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-conclusion-building-maintainable-react-applications">Conclusion: Building Maintainable React Applications</h2>
<p>Managing shared state complexity is one of the most important skills to have for building scalable React applications. The key is choosing the right tool for each situation and following established patterns.</p>
<h3 id="heading-summary-of-approaches">Summary of approaches</h3>
<p><strong>Start simple and scale up:</strong></p>
<ol>
<li><p><strong>Local state</strong> for component-specific data</p>
</li>
<li><p><strong>Context</strong> for moderate shared state that doesn't change frequently</p>
</li>
<li><p><strong>State management libraries</strong> for complex, frequently-changing global state</p>
</li>
<li><p><strong>Custom hooks</strong> for reusable stateful logic</p>
</li>
</ol>
<h3 id="heading-key-principles-to-remember">Key principles to remember</h3>
<p><strong>1. Principle of least power</strong>: Use the simplest solution that meets your needs</p>
<ul>
<li><p>Don't use Redux for a theme toggle</p>
</li>
<li><p>Don't use local state for user authentication</p>
</li>
<li><p>Don't use Context for rapidly changing data</p>
</li>
</ul>
<p><strong>2. Separation of concerns</strong>: Keep related state together, unrelated state apart</p>
<ul>
<li><p>Group user state separately from cart state</p>
</li>
<li><p>Don't mix temporary UI state with persistent data</p>
</li>
<li><p>Separate actions from selectors</p>
</li>
</ul>
<p><strong>3. Performance matters</strong>: Optimize for your specific use case</p>
<ul>
<li><p>Memoize context values to prevent unnecessary re-renders</p>
</li>
<li><p>Use selective subscriptions in state management libraries</p>
</li>
<li><p>Split large contexts into smaller, focused ones</p>
</li>
</ul>
<p><strong>4. Maintainability first</strong>: Write code that future developers (including yourself) can understand</p>
<ul>
<li><p>Use descriptive names for state and actions</p>
</li>
<li><p>Handle loading and error states consistently</p>
</li>
<li><p>Write comprehensive tests for your state logic</p>
</li>
</ul>
<h3 id="heading-the-evolution-of-a-typical-application">The evolution of a typical application</h3>
<p>Most successful React applications follow this pattern:</p>
<p><strong>Phase 1: Simple local state</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Start here for new features</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ContactForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-comment">// Simple and focused</span>
}
</code></pre>
<p><strong>Phase 2: Context for shared data</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Move to Context when multiple components need the same data</span>
<span class="hljs-keyword">const</span> UserContext = createContext();
<span class="hljs-comment">// Used by Header, Sidebar, UserProfile components</span>
</code></pre>
<p><strong>Phase 3: State management library for complex interactions</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Scale to Redux/Zustand when state becomes complex</span>
<span class="hljs-keyword">const</span> useAppStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">cart</span>: { <span class="hljs-attr">items</span>: [], <span class="hljs-attr">total</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">orders</span>: [],
  <span class="hljs-comment">// Many interconnected pieces of state</span>
}));
</code></pre>
<p><strong>Phase 4: Custom hooks for reusable patterns</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Extract reusable logic into custom hooks</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useApi</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-comment">// Reusable API logic with loading, error, and retry</span>
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useLocalStorage</span>(<span class="hljs-params">key, defaultValue</span>) </span>{
  <span class="hljs-comment">// Reusable localStorage sync</span>
}
</code></pre>
<h3 id="heading-final-recommendations">Final recommendations</h3>
<p><strong>For beginners</strong>: Start with local state and Context. Master these before moving to state management libraries.</p>
<p><strong>For intermediate developers</strong>: Learn one state management library well (Zustand or Redux Toolkit). Focus on proper error handling and performance optimization.</p>
<p><strong>For advanced developers</strong>: Experiment with different patterns and create reusable abstractions. Focus on team consistency and maintainable architectures.</p>
<p><strong>For teams</strong>: Establish conventions early and document your state management patterns. Code reviews should focus on proper state placement and performance implications.</p>
<p>The goal is not to eliminate all complexity, but to manage it in a way that scales with your application and team. Every piece of shared state should have a clear owner, predictable update patterns, and proper error handling.</p>
<p>Remember: the best state management solution is often a combination of approaches. A well-architected React application uses local state for local concerns, Context for moderate sharing, state management libraries for complex global state, and custom hooks for reusable logic.</p>
<p>By following these principles and patterns, you'll build React applications that are not only functional but also maintainable, performant, and enjoyable to work with as they grow in complexity.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Streams and Services for Flutter State ]]>
                </title>
                <description>
                    <![CDATA[ Among the many state management architectures in Flutter, combining Dart streams with singleton classes (services) is an unpopular yet easy architecture. In this article, we’ll explore how to achieve this combination for app-wide state in Flutter. Ta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/flutter-streams-and-services/</link>
                <guid isPermaLink="false">66f3dcb00eb033fac26d3822</guid>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Obum ]]>
                </dc:creator>
                <pubDate>Wed, 25 Sep 2024 09:49:36 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727130776096/a52147fe-e05a-45e7-af73-9f7a9a8510b5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Among the many state management architectures in Flutter, combining Dart streams with singleton classes (services) is an unpopular yet easy architecture.</p>
<p>In this article, we’ll explore how to achieve this combination for app-wide state in Flutter.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-app-wide-state-in-flutter">What is App-wide State in Flutter?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-stream-in-dart">What is a Stream in Dart?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-stream-in-dart">How to Create a Stream in Dart</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-singleton-class-instances-or-services">How to Create Singleton Class Instances (or Services)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manipulate-state-streams-within-services">How to Manipulate State (streams) Within Services</a></p>
</li>
<li><p><a target="_blank" href="https://untitled+.vscode-resource.vscode-cdn.net/Untitled-1#heading-how-to-manipulate-state-streams-within-services">How to Use Dart Streams in Flutter Widgets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-a-service-depend-on-another">How to Make a Service Depend on Another</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-improve-streams-with-rxdart-classes-and-extensions">How to Improve Streams with rxdart Classes and Extensions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-update-state-in-applifecycle-callbacks">How to Update State in AppLifecycle Callbacks</a></p>
</li>
<li><p><a target="_blank" href="https://untitled+.vscode-resource.vscode-cdn.net/Untitled-1#heading-how-to-improve-streams-with-rxdart-classes-and-extensions">Flexibi</a><a class="post-section-overview" href="#heading-flexibility-in-state-management">l</a><a target="_blank" href="https://untitled+.vscode-resource.vscode-cdn.net/Untitled-1#heading-how-to-improve-streams-with-rxdart-classes-and-extensions">ity in</a> <a class="post-section-overview" href="#heading-flexibility-in-state-management">State Management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-what-is-app-wide-state-in-flutter">What is App-wide State in Flutter?</h2>
<p>App-wide state comprises all variables that are relevant to multiple widgets at the same time. By app-wide state, we don't mean the state that is attached to <code>StatefulWidgets</code>. Those are ephemeral state. Updating them requires local or scoped calls to <a target="_blank" href="https://api.flutter.dev/flutter/widgets/State/setState.html">setState</a>.</p>
<p>In Flutter, app-wide state usually has a separate logical management from UI code. This separated logic is called a state management architecture. We have many state management architectures with which we can engineer app-wide state. Examples include <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">Provider</a>, <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">InheritedWidget</a>, <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">Riverpod</a>, <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">Bloc</a>, <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">Redux</a>, <a target="_blank" href="https://github.com/obumnwabude/write/blob/main/2024/flutter/get-the-link">Stacked</a>, and so on. Each of these state management architectures are efficient, good, and opinionated.</p>
<p>While your choice of architecture could vary based on different factors, consider adopting the following architecture in your projects. It involves using Dart streams and services (singleton classes) for keeping track of your app's state.</p>
<h2 id="heading-what-is-a-stream-in-dart">What is a Stream in Dart?</h2>
<p>A <a target="_blank" href="https://dart.dev/libraries/dart-async#stream">stream</a> continuously emits values. You can listen to a stream and constantly get new values when they are emitted. Streams in Dart are the equivalent of <a target="_blank" href="https://rxjs.dev/guide/observable"><code>Observable</code></a> in JavaScript.</p>
<p>In Dart, streams are different from <a target="_blank" href="https://dart.dev/libraries/dart-async#future">futures</a>. The difference is that while a future resolves to one value, a stream will continuously emit various values during its life.</p>
<p>Let's say we have a <code>counter</code> stream that keeps track of some current integer count. This count could be incremented or decremented. To use the values emitted by this <code>counter</code> stream, you listen to the <code>counter</code>. Listening implies calling the <code>.listen</code> method on the stream and handling the emitted value.</p>
<pre><code class="lang-dart">counter.listen((<span class="hljs-built_in">int</span> value) =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'Got <span class="hljs-subst">$value</span>.'</span>));
</code></pre>
<h2 id="heading-how-to-create-a-stream-in-dart">How to Create a Stream in Dart</h2>
<p>The <a target="_blank" href="https://dart.dev/libraries/dart-async#stream"><code>Stream</code></a> class comes with multiple factory constructors. They allow you to create various streams for various purposes. They include:</p>
<ul>
<li><p><code>Stream.empty</code></p>
</li>
<li><p><code>Stream.value</code></p>
</li>
<li><p><code>Stream.error</code></p>
</li>
<li><p><code>Stream.fromFuture</code></p>
</li>
<li><p><code>Stream.fromFutures</code></p>
</li>
<li><p><code>Stream.fromIterable</code></p>
</li>
<li><p><code>Stream.multi</code></p>
</li>
<li><p><code>Stream.periodic</code></p>
</li>
<li><p><code>Stream.eventTransformed</code></p>
</li>
</ul>
<p>Each constructor serves a specific purpose as its name suggests.</p>
<p>Another technique of creating a <code>Stream</code> is by obtaining it from a <code>StreamController</code>. You will have to create the <code>StreamController</code> yourself. The advantage of doing this is that the controller allows you to <em>add</em> values to it. When you add values to the controller, they get emitted to listeners of its stream.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'dart:async'</span>;

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> counterCtrl = StreamController&lt;<span class="hljs-built_in">int</span>&gt;();
  counterCtrl.stream.listen(<span class="hljs-built_in">print</span>);
  counterCtrl.add(<span class="hljs-number">1</span>); <span class="hljs-comment">// prints 1</span>
}
</code></pre>
<p>The problem with the default <code>StreamController</code> from the <code>dart:async</code> library is that it allows only one listener. It is unicast. If you attempt attaching another listener to this stream obtained from <code>StreamController</code>, it will throw a "bad state" error.</p>
<p>This issue is solved by the <code>BehaviorSubject</code> class from the <a target="_blank" href="https://pub.dev/packages/rxdart"><code>rxdart</code></a> package. Technically, <code>BehaviorSubject</code> is a <code>StreamController</code>. The difference is that it has more features like:</p>
<ol>
<li><p>Allows multiple listeners (very important).</p>
</li>
<li><p>Caches the latest emitted value or error.</p>
</li>
<li><p>Emits the latest cached value/error to a new listener once it newly subscribes.</p>
</li>
<li><p>Allows you to synchronously read the current (or last emitted) value from it.</p>
</li>
<li><p>Allows you to add values to it if it doesn't yet have any listener (the default <code>StreamController</code> doesn’t allow this).</p>
</li>
</ol>
<p>The <code>rxdart</code> package extends the capabilities of Dart streams. For example, it provides you with <code>BehaviorSubject</code>. Also, it exposes classes and extensions that allow more stream manipulations. To use the <code>rxdart</code> package, add it to your project's dependencies from pub using the following command:</p>
<pre><code class="lang-bash">flutter pub add rxdart
</code></pre>
<p>Then import it in your project's Dart files. From there, you can create <code>BehaviorSubject</code> (more robust <code>StreamController</code>) that can allow multiple listeners while allowing you to control them (adding values to the streams).</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-comment">// Create a BehaviorSubject.</span>
  <span class="hljs-comment">//</span>
  <span class="hljs-comment">// Asides from creating the BehaviorSubject, we can also  </span>
  <span class="hljs-comment">// immediately add a value to it using Dart's cascade operator.</span>
  <span class="hljs-keyword">final</span> counterBS = BehaviorSubject&lt;<span class="hljs-built_in">int</span>&gt;()..add(<span class="hljs-number">0</span>);

  counterBS.stream.listen(<span class="hljs-built_in">print</span>); <span class="hljs-comment">// prints 0</span>
  counterBS.stream.listen(<span class="hljs-built_in">print</span>); <span class="hljs-comment">// prints 0</span>
  counterBS.add(<span class="hljs-number">1</span>); <span class="hljs-comment">// prints 1 twice</span>
}
</code></pre>
<p>Now that we can create streams (and listen to them), we need the exact same streams to be available to every part of our Flutter apps.</p>
<p>To ensure that it is the same instance of streams that different parts of our Flutter apps are accessing, we can expose the streams from singleton class instances that we create in the project.</p>
<h2 id="heading-how-to-create-singleton-class-instances-or-services">How to Create Singleton Class Instances (or Services)</h2>
<p>When something is called a singleton, it means only one of it exists. For example, we can say the sun is a singleton star because we have only one sun.</p>
<p>When it comes to programming, we use a singleton when we need the same copy of an object everywhere. Already, the <a target="_blank" href="https://en.m.wikipedia.org/wiki/Static_variable"><code>static</code></a> properties of a class are singletons to every instance of that class. When you declare a field or method as <code>static</code>, you're telling the runtime engine to always reuse the same static item.</p>
<p>This explains why <code>static</code> properties are used as constants. It's another reason why we use them without instantiating an object. Furthermore, in Flutter, we conventionally use static properties as a means to obtain new or existing instances of a class. For example, many Flutter classes (<code>MediaQuery</code>, <code>Navigator</code>, <code>ThemeData</code>, and so on) have a static <code>.of</code> method for obtaining their instances.</p>
<p>In this streams and services architecture, we expose only one instance from a class with the <code>static</code> keyword. At the same time, we hide that class constructor. Hiding the constructor ensures that no other Dart code outside the Dart file can create another instance of the same class. Doing this maintains the instance as a singleton.</p>
<p>Following common conventions, we can call this class a service. Any other Dart file in the project can listen to the exposed stream(s) from the service class and always get updated values emitted to it.</p>
<p>Services here are holders of app-wide state. Each service is a logical container of related features. In any other part of the code, through these services, we can access app-wide state variables (in our case, streams). In a production application, we could have an authentication service, another for notifications, another for files, and so on.</p>
<p>To have an app-wide available service (singleton class) with a stream in it:</p>
<ol>
<li><p>Create a service class.</p>
</li>
<li><p>Create a private constructor (so that no other Dart code outside the class can instantiate it).</p>
</li>
<li><p>Create a static private instance of that very class.</p>
</li>
<li><p>Expose this private instance as the singleton.</p>
</li>
<li><p>Create a private <code>BehaviorSubject</code> in that class.</p>
</li>
<li><p>Expose the <code>BehaviorSubject</code> stream as a public static getter from the class.</p>
</li>
</ol>
<pre><code class="lang-dart"><span class="hljs-comment">/* In counter_service.dart file */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;

<span class="hljs-comment">// 1. Create a class</span>
<span class="hljs-comment">// </span>
<span class="hljs-comment">// The class name with "Service" appended to it indicates </span>
<span class="hljs-comment">// that it is an app-wide state object.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterService</span> </span>{
  <span class="hljs-comment">// 2. Create a private constructor.</span>
  <span class="hljs-comment">//</span>
  <span class="hljs-comment">// This "just-underscore" constructor works. If we want, we could  </span>
  <span class="hljs-comment">// still add a name after the underscore. The main thing is that </span>
  <span class="hljs-comment">// underscore makes the constructor to be a private one.</span>
  CounterService._();

  <span class="hljs-comment">// 3. Create a static private instance.</span>
  <span class="hljs-comment">// </span>
  <span class="hljs-comment">// Prefixing underscore (_) to the variable name makes it private.</span>
  <span class="hljs-comment">// By being private, no other Dart code outside this file can directly </span>
  <span class="hljs-comment">// access it.</span>
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> _instance = CounterService._();

  <span class="hljs-comment">// 4. Expose this private instance as the singleton.</span>
  <span class="hljs-keyword">static</span> CounterService <span class="hljs-keyword">get</span> instance =&gt; _instance;

  <span class="hljs-comment">// 5. Create a private BehaviorSubject.</span>
  <span class="hljs-keyword">final</span> _counterBS = BehaviorSubject&lt;<span class="hljs-built_in">int</span>&gt;()..add(<span class="hljs-number">0</span>);

  <span class="hljs-comment">// 6. Expose the BehaviorSubject's Stream.</span>
  Stream&lt;<span class="hljs-built_in">int</span>&gt; <span class="hljs-keyword">get</span> countStream =&gt; _counterBS.stream;

  <span class="hljs-comment">// Also, if need be, expose the BehaviorSubject's current as a getter.</span>
  <span class="hljs-built_in">int</span> <span class="hljs-keyword">get</span> currentCount =&gt; _counterBS.value;
}

<span class="hljs-comment">/* In any other Dart file in the project */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'counter_service.dart'</span>

<span class="hljs-comment">// Attach a listener to the stream</span>
CounterService.instance.countStream.listen((count) {
   <span class="hljs-comment">// Use the count as use wish. Code you write within this </span>
   <span class="hljs-comment">// listener's block will be called whenever count is </span>
   <span class="hljs-comment">// update/re-emitted.</span>

   <span class="hljs-built_in">print</span>(count); <span class="hljs-comment">// prints 0</span>
});

<span class="hljs-comment">// Read the current stream value just once without subscribing</span>
<span class="hljs-built_in">print</span>(CounterService.instance.currentCount); <span class="hljs-comment">// prints 0</span>
</code></pre>
<h2 id="heading-how-to-manipulate-state-streams-within-services">How to Manipulate State (Streams) Within Services</h2>
<p>Most times, each service will have multiple streams. This is as expected, given that, for a given logical state feature, there would be multiple variables affecting it. Therefore, where need be, don't hesitate to declare multiple <code>BehaviorSubject</code> (while exposing their streams) within the same service class.</p>
<p>For each stream, you want to control its data. That's why we are using <code>BehaviorSubject</code>, so that we can add values to it when there is a need to update state.</p>
<p>Different events (whether from the user or your servers) can be the cause of such state updates. You want to trigger state updates (or add values to streams) anytime those events occur.</p>
<p>You could always poll your backend and emit changes to your streams if any event happens. You could also emit values based on changes in other services. In addition, if need be, services should also expose relevant methods that will update their streams. In turn, other parts of the app can call these methods and trigger changes. The obvious advantage is that every listener will respectively get the new stream value emitted to them.</p>
<pre><code class="lang-dart"><span class="hljs-comment">/* In counter_service.dart file */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterService</span> </span>{
  CounterService._();
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> _instance = CounterService._();
  <span class="hljs-keyword">static</span> CounterService <span class="hljs-keyword">get</span> instance =&gt; _instance;

  <span class="hljs-keyword">final</span> _counterBS = BehaviorSubject&lt;<span class="hljs-built_in">int</span>&gt;()..add(<span class="hljs-number">0</span>);
  Stream&lt;<span class="hljs-built_in">int</span>&gt; <span class="hljs-keyword">get</span> countStream =&gt; _counterBS.stream;
  <span class="hljs-built_in">int</span> <span class="hljs-keyword">get</span> currentCount =&gt; _counterBS.value;

  <span class="hljs-comment">// Incrementing/Decrementing the counter will trigger state updates.</span>
  <span class="hljs-keyword">void</span> incrementCount() =&gt; _counterBS.add(currentCount + <span class="hljs-number">1</span>);
  <span class="hljs-keyword">void</span> decrementCount() =&gt; _counterBS.add(currentCount - <span class="hljs-number">1</span>);
}

<span class="hljs-comment">/* In another Dart file in the project */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'counter_service.dart'</span>

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> service = CounterService.instance;
  service.countStream.listen(<span class="hljs-built_in">print</span>); <span class="hljs-comment">// prints 0</span>
  service.incrementCount(); <span class="hljs-comment">// causes 1 to be printed</span>
  service.decrementCount(); <span class="hljs-comment">// causes 0 to be printed</span>
}
</code></pre>
<p>For a more concrete example, let's say we have an <code>AuthenticationService</code>. It declares some <code>_userBS</code> and exposes a <code>currentUser</code> stream with type <code>Stream&lt;User?&gt;</code>, the user will be valid if authenticated or <code>null</code> if signed out. This auth service will naturally have <code>signIn</code> and <code>signOut</code> which can both add values to <code>_userBS</code>. The sign-up and login screens can each call <code>signIn</code> whereas the “switch account” and “log out” buttons can each call <code>signOut</code>.</p>
<pre><code class="lang-dart"><span class="hljs-comment">/* In user.dart */</span>
<span class="hljs-comment">// A simple user with only email and username for demo purposes. </span>
<span class="hljs-comment">// Your User model/schema would have more properties.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> email;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> username;

  <span class="hljs-keyword">const</span> User(<span class="hljs-keyword">this</span>.email, <span class="hljs-keyword">this</span>.username);
}

<span class="hljs-comment">/* In authentication_service.dart */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'user.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationService</span> </span>{
   AuthenticationService._();
   <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> _instance = AuthenticationService._();
   <span class="hljs-keyword">static</span> AuthenticationService instance =&gt; _instance;

   <span class="hljs-comment">// User BehaviorSubject and its stream.</span>
   <span class="hljs-keyword">final</span> _userBS = BehaviorSubject&lt;User?&gt;()..add(<span class="hljs-keyword">null</span>);
   Stream&lt;User?&gt; <span class="hljs-keyword">get</span> currentUser =&gt; _userBS.stream;

   <span class="hljs-comment">// signIn adds a new User to the stream.</span>
   <span class="hljs-keyword">void</span> signIn(<span class="hljs-built_in">String</span> email, <span class="hljs-built_in">String</span> username}) {
     _userBS.add(User(email, username));
   }

   <span class="hljs-comment">// signOut sets the currentUser as null</span>
   <span class="hljs-keyword">void</span> signOut() =&gt; _userBS.add(<span class="hljs-keyword">null</span>);

   <span class="hljs-comment">// signIn and signOut methods that tamper the state could do other </span>
   <span class="hljs-comment">// actions like recording analytics or carrying out navigation.</span>
   <span class="hljs-comment">// Also, they could do some validation or run some checks before</span>
   <span class="hljs-comment">// emitting values. The idea is that you get comfortable with</span>
   <span class="hljs-comment">// updating the values of BehaviorSubject (hence emitting streams) </span>
   <span class="hljs-comment">// from controlled methods within the service.</span>
}
</code></pre>
<p>Another state manipulation point is at initializing services. Some streams may warrant an asynchronous initializer before they should be used. You can define <code>init</code> methods in the services, and call the methods before calling <a target="_blank" href="https://api.flutter.dev/flutter/widgets/runApp.html"><code>runApp</code></a> in the topmost main method in Flutter.</p>
<p><code>init</code> methods may be "localStorage"-saved values from previous app runs. They can make API calls, check permissions, or set up <a target="_blank" href="https://api.flutter.dev/flutter/services/EventChannel-class.html">EventChannel</a> listeners. When you call them before <code>runApp</code>, be sure to call <code>ensureInitialized()</code> from <a target="_blank" href="https://api.flutter.dev/flutter/widgets/WidgetsFlutterBinding-class.html"><code>WidgetsFlutterBinding</code></a> before initializing the services. This is especially mandatory if any of the service <code>init</code> code will access a <a target="_blank" href="https://docs.flutter.dev/platform-integration/platform-channels"><code>PlatformChannel</code></a>.</p>
<pre><code class="lang-dart"><span class="hljs-comment">/* authentication_service.dart */</span>
<span class="hljs-comment">// ... imports</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationService</span> </span>{
  <span class="hljs-comment">// ... other code</span>

  <span class="hljs-comment">// initialize the service and carry-out other setups if need be.</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; init() <span class="hljs-keyword">async</span> =&gt; _userBS.add(<span class="hljs-keyword">await</span> _fetchSavedUser());
}

<span class="hljs-comment">/* main.dart */</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'authentication_service.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  WidgetsFlutterBinding.ensureInitialized();

  <span class="hljs-comment">// Initialize the service to be sure it is up and running before</span>
  <span class="hljs-comment">// launching the app. You could also initialize other services here.</span>
  <span class="hljs-comment">// Only do this if they are carrying out asynchronous executions,</span>
  <span class="hljs-comment">// and the results need to be ready before the UI launches.</span>
  <span class="hljs-keyword">await</span> AuthenticationService.instance.init();

  runApp(<span class="hljs-keyword">const</span> MyApp());
}
</code></pre>
<h2 id="heading-how-to-use-dart-streams-in-flutter-widgets">How to Use Dart Streams in Flutter Widgets</h2>
<p>Flutter comes with a built-in <a target="_blank" href="https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html">StreamBuilder</a> widget. It takes a stream and a builder function. This builder function will get a <code>BuildContext</code> and snapshot data about the stream. The function should always return a widget.</p>
<p>When building UIs, you can wrap UI parts that depend on or display values emitted from app-wide streams in <code>StreamBuilders</code>. That way, once the stream emits a value, Flutter auto-rebuilds the children widget of the <code>StreamBuilders</code> with the latest values.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'counter_service.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> StreamBuilder&lt;<span class="hljs-built_in">int</span>&gt;(
      stream: CounterService.instance.countStream, <span class="hljs-comment">// The stream to listen to</span>
      initialData: CounterService.instance.currentCount, <span class="hljs-comment">// Initial value</span>
      builder: (context, snapshot) {
        <span class="hljs-comment">// Check if the snapshot has data</span>
        <span class="hljs-keyword">if</span> (snapshot.hasData) {
          <span class="hljs-keyword">return</span> Text(<span class="hljs-string">'Counter: <span class="hljs-subst">${snapshot.data}</span>'</span>, style: TextStyle(fontSize: <span class="hljs-number">24</span>));
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// Handle any error or empty state</span>
          <span class="hljs-keyword">return</span> Text(<span class="hljs-string">'Loading...'</span>, style: TextStyle(fontSize: <span class="hljs-number">24</span>));
        }
      },
    );
  }
}
</code></pre>
<p><code>StreamBuilders</code> are great tools. However, there are times when it is not suitable to use them. For example:</p>
<ul>
<li><p>When a given UI screen depends on multiple streams that are exposed by the same or different services.</p>
</li>
<li><p>When you want to do some computation on the stream values before rendering them in the UI.</p>
</li>
</ul>
<p>In those cases, we need to listen to the streams separately in <code>initState</code>, set values through <code>setState</code> calls (to update the UI), and dispose of the <code>StreamSubscriptions</code> in the StatefulWidget's <code>dispose</code> method.</p>
<p>Listening to the streams separately allows us to perform any customizations or to merge data when the streams emit values. In addition, we make our UI code easier to read given that we’ve taken out logic-related code from the build method. However, we should do this only when necessary: <code>StreamBuilders</code> will, most of the time, be sufficient.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'dart:async'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'counter_service.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterStatefulWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{
  <span class="hljs-keyword">const</span> CounterStatefulWidget({<span class="hljs-keyword">super</span>.key});

  <span class="hljs-meta">@override</span>
  _CounterStatefulWidgetState createState() =&gt; _CounterStatefulWidgetState();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_CounterStatefulWidgetState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State</span>&lt;<span class="hljs-title">CounterStatefulWidget</span>&gt; </span>{
  <span class="hljs-keyword">late</span> StreamSubscription&lt;<span class="hljs-built_in">int</span>&gt; counterSub;
  <span class="hljs-built_in">int</span> count = CounterService.instance.currentCount;

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> initState() {
    <span class="hljs-keyword">super</span>.initState();

    <span class="hljs-comment">// Initialize the stream subscription</span>
    counterSub = CounterService.instance.countStream.listen((count) {
      <span class="hljs-comment">// Update state on new stream value</span>
      setState(() =&gt; <span class="hljs-keyword">this</span>.count = count);
    });
  }

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> dispose() {
    <span class="hljs-comment">// Dispose of the stream subscription to avoid memory leaks</span>
    counterSub.cancel();
    <span class="hljs-keyword">super</span>.dispose();
  }

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Text(<span class="hljs-string">'Counter: <span class="hljs-subst">$count</span>'</span>, style: TextStyle(fontSize: <span class="hljs-number">24</span>));
  }
}
</code></pre>
<p>The example above demonstrates listening and disposing from outside the build method. The example is not a good use case of when you should do that.</p>
<h2 id="heading-how-to-make-a-service-depend-on-another">How to Make a Service Depend on Another</h2>
<p>In complex applications, it's common to have services that depend on each other. The dependent service can listen to streams and call methods of the independent service. Also, the dependent service can import and reference the independent service just as we’ve been doing in UI code above.</p>
<p>For instance, if we are building an e-commerce app, a <code>CartService</code> may depend on an <code>AuthenticationService</code> to fetch carts and orders for the signed-in user. If the user signs out, some <code>currentUser</code> stream in the <code>AuthenticationService</code> will emit <code>null</code>. In turn, the listening <code>CartService</code> will update the cart. When next a new user signs in, it will fetch the new cart.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'authentication_service.dart'</span>;

<span class="hljs-comment">// Item model representing a cart item.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CartItem</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> quantity;

  <span class="hljs-keyword">const</span> CartItem(<span class="hljs-keyword">this</span>.name, <span class="hljs-keyword">this</span>.quantity);
}

<span class="hljs-comment">// CartService to manage the user's shopping cart.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CartService</span> </span>{
  <span class="hljs-comment">// ...</span>

  <span class="hljs-comment">// Dependency on AuthenticationService.</span>
  <span class="hljs-keyword">final</span> _auth = AuthenticationService.instance;

  <span class="hljs-keyword">final</span> _cartItemsBS = BehaviorSubject&lt;<span class="hljs-built_in">List</span>&lt;CartItem&gt;&gt;();
  Stream&lt;<span class="hljs-built_in">List</span>&lt;CartItem&gt;&gt; <span class="hljs-keyword">get</span> cartStream =&gt; _cartItemsBS.stream;

  CartService() {
    <span class="hljs-comment">// Listen to the currentUser stream in AuthenticationService.</span>
    _auth.currentUserStream.listen((user) {
      <span class="hljs-keyword">if</span> (user == <span class="hljs-keyword">null</span>) {
        <span class="hljs-comment">// User signed out, clear the cart.</span>
        _clearCart();
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// User signed in, fetch their cart.</span>
        _fetchCartForUser(user.email);
      }
    });
  }

  <span class="hljs-comment">// Method to clear the cart (called on sign-out).</span>
  <span class="hljs-keyword">void</span> _clearCart() {
    _cartItemsBS.add([]);  <span class="hljs-comment">// Emit an empty list to clear the cart.</span>
  }

  <span class="hljs-comment">// Method to fetch the cart for a signed-in user (simulated).</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; _fetchCartForUser(<span class="hljs-built_in">String</span> email) <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// ...</span>
  }
}
</code></pre>
<p>Watch out for <a target="_blank" href="https://en.wikipedia.org/wiki/Circular_dependency">circular dependency</a> problems when your services depend on each other. Circular dependency occurs when two services inter-depend on themselves. This scenario is usually inevitable as business logic grows.</p>
<p>When faced with it, lift the state they want to co-share to a different service and import this new service into the others. Another solution is to use Dart’s <code>late</code> keywords when importing the interdependent services. You can also find ways to ensure that variable accessing is within functions and not at some top-level declaration.</p>
<h2 id="heading-how-to-improve-streams-with-rxdart-classes-and-extensions">How to Improve Streams with rxdart Classes and Extensions</h2>
<p>Asides from having service methods that update streams, you can also have new or improved streams based on existing ones, by using <code>rxdart</code> classes and extensions.</p>
<p>An example class is <a target="_blank" href="https://pub.dev/documentation/rxdart/latest/rx/CombineLatestStream-class.html"><code>CombineLatestStream</code></a>. It takes multiple streams and a combiner function to return a new stream that will re-emit the combined latest values of the source streams (depending on the optional combiner).</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MultipliedCounterService</span> </span>{
  <span class="hljs-comment">// ... </span>

  <span class="hljs-keyword">final</span> _counterBS = BehaviorSubject&lt;<span class="hljs-built_in">int</span>&gt;()..add(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">final</span> _multiplierBS = BehaviorSubject&lt;<span class="hljs-built_in">int</span>&gt;()..add(<span class="hljs-number">2</span>);

  Stream&lt;<span class="hljs-built_in">int</span>&gt; <span class="hljs-keyword">get</span> combinedStream =&gt; CombineLatestStream(
        [_counterBS.stream, _multiplierBS.stream],
        (values) =&gt; values[<span class="hljs-number">0</span>] * values[<span class="hljs-number">1</span>],
      );

  <span class="hljs-keyword">void</span> incrementCounter() =&gt; _counterBS.add(_counterBS.value + <span class="hljs-number">1</span>);
  <span class="hljs-keyword">void</span> changeMultiplier(<span class="hljs-built_in">int</span> mul) =&gt; _multiplierBS.add(mul);
}
</code></pre>
<p>Another good stream method is <a target="_blank" href="https://pub.dev/documentation/rxdart/latest/rx/DebounceExtensions/debounceTime.html"><code>debounceTime</code></a>. This is a stream extension that is useful for ignoring frequent emissions and processing the latest value after a delay (like when searching). An emission will only occur after the set duration and when there is no other emission in between that time. It helps avoid excessive API calls by waiting for a period of inactivity before emitting the latest value.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:rxdart/rxdart.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SearchService</span> </span>{
  <span class="hljs-comment">// ... </span>

  <span class="hljs-keyword">final</span> _searchQueryBS = BehaviorSubject&lt;<span class="hljs-built_in">String</span>&gt;()..add(<span class="hljs-string">''</span>);

  <span class="hljs-comment">// Stream with debouncing to emit values only after a</span>
  <span class="hljs-comment">// 300ms delay. For example: keystrokes will be bundled at once.</span>
  Stream&lt;<span class="hljs-built_in">String</span>&gt; <span class="hljs-keyword">get</span> debouncedSearchQueryStream =&gt;
      _searchQueryBS.stream.debounceTime(<span class="hljs-built_in">Duration</span>(milliseconds: <span class="hljs-number">300</span>));

  <span class="hljs-keyword">void</span> updateSearchQuery(<span class="hljs-built_in">String</span> query) =&gt; _searchQueryBS.add(query);
}
</code></pre>
<p>The <code>rxdart</code> package provides more classes and stream extensions that will be useful to you, even if you don’t use this architecture. Check them out later on.</p>
<h2 id="heading-how-to-update-state-in-applifecycle-callbacks">How to Update State in AppLifecycle Callbacks</h2>
<p>When a user minimizes or leaves your application and comes back, some external things you rely on for data may have changed.</p>
<p>For example, when you prompt a user to grant any permissions, the operating system displays a popup over your application. Programmatically, the displayed popup caused your app to lose focus or go into background mode. When the popup is gone, your app resumes focus and you need to detect whether you got the permissions.</p>
<p>Equally, if you are managing the contents of a specific File Explorer Directory within your application (like converted music, encrypted docs, call logs, and so on), when your app goes in background, there could be changes to that directory from the user, which are worth detecting when the user comes back.</p>
<p>Sometimes, you may want to know when the user comes back to your application for authentication purposes, like terminating a session if they stayed away for too long and they need to re-authenticate. Other times, you may want to refresh app contents, to retain the user, as you can do if building a social media app.</p>
<p>In all these cases, we need a way to programmatically know when our app comes back to the user's focus after the user had left. Luckily, Flutter provides us with <a target="_blank" href="https://api.flutter.dev/flutter/dart-ui/AppLifecycleState.html"><code>AppLifecycleState</code></a> and a way to react to changes to them.</p>
<p>An app’s lifecycle refers to its various states while it is running. In Flutter, <code>AppLifecycleState</code> includes detached, resumed, inactive, hidden, and paused. In the above example cases, anytime the user comes back to the app, the app’s lifecycle state becomes <code>AppLifecycleState.resumed</code>.</p>
<p>We can react to lifecycle changes and call our service methods when a particular state occurs. To listen to lifecycle changes, your service class should add the <code>WidgetsBindingObserver</code> mixin to its declaration. Then you should override <code>didChangeAppLifecycleState</code> with a callback. This callback should handle states it is interested in.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PermissionService</span> <span class="hljs-title">with</span> <span class="hljs-title">WidgetsBindingObserver</span> </span>{
  <span class="hljs-comment">// ...</span>

  Future&lt;<span class="hljs-keyword">void</span>&gt; checkPermissions() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// ... </span>
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; didChangeAppLifecycleState(AppLifecycleState state) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">if</span> (state == AppLifecycleState.resumed) {
      <span class="hljs-keyword">await</span> checkPermissions();
    }
    <span class="hljs-comment">// you can check for the other states too and handle as expected.</span>
  }
}
</code></pre>
<h2 id="heading-flexibility-in-state-management">Flexibility in State Management</h2>
<p>There are multiple choices and flavors for state management in the Flutter community. Most of the time, the same features can always be built with any state management of choice.</p>
<p>With that in mind, be flexible with state management architectures in Flutter. They are not some hard cast rules. Bend and play around with them to suit your unique app cases as there is no "one size fits all" here.</p>
<p>You can play around with streams and services. You could use <a target="_blank" href="https://pub.dev/packages/get_it">getIt</a> for obtaining singletons. <code>getIt</code> also allows you to obtain scoped singletons, that is, singletons attached to a navigator or a logical part of features (within a search for example).</p>
<p>You can also combine this architecture with others. Like declaring and managing streams as explained here but in providers or cubits. Or bringing in features of other architectures into services you declare as described in this article.</p>
<p>Just be sure you know what you're doing and that you understand how to coordinate the variables representing app state. Preferably, document your choice of architectures in your codebase for future reference.</p>
<h2 id="heading-summary">Summary</h2>
<p>In summary, we have explored an efficient architecture for managing app-wide state in Flutter using Dart streams and singleton services.</p>
<p>We've also seen how to manipulate streams, how to use them in UI code, make services depend on each other, improve streams using <code>rxdart</code>, and handle app lifecycle changes.</p>
<p>Remember that state management in Flutter is flexible, and no one solution fits all. Tailor your choice of state management architecture to fit your specific app needs.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Data Flow in Redux Explained – A State Management Handbook ]]>
                </title>
                <description>
                    <![CDATA[ In complex React applications, managing application state effectively can become a challenge. This is where Redux, a predictable state management library, steps in. By introducing a unidirectional data flow, Redux brings order and clarity to how data... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-data-flows-in-redux/</link>
                <guid isPermaLink="false">66c4c3d48e05d0e4345147c6</guid>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Wed, 03 Jul 2024 13:45:02 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/Data-Flow-in-Redux-Explained-Cover-No-Photo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In complex React applications, managing application state effectively can become a challenge. This is where Redux, a predictable state management library, steps in.</p>
<p>By introducing a unidirectional data flow, Redux brings order and clarity to how data updates and interacts within your React components.</p>
<p>This article discusses the inner workings of Redux, specifically focusing on how data flows throughout your application. We'll explore core concepts like the Redux store, actions, reducers, and selectors, along with practical examples of how they work together to seamlessly manage your application state.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-redux">What is Redux?</a></li>
<li><a class="post-section-overview" href="#heading-why-use-redux-for-data-management">Why Use Redux for Data Management?</a></li>
<li><a class="post-section-overview" href="#heading-core-concepts-of-redux-data-flow">Core Concepts of Redux Data Flow</a>  </li>
<li><a class="post-section-overview" href="#heading-unidirectional-data-flow">Unidirectional Data Flow</a>  </li>
<li><a class="post-section-overview" href="#heading-benefits-of-unidirectional-data-flow">Benefits of Unidirectional Data Flow</a></li>
<li><a class="post-section-overview" href="#heading-state-management-with-redux-store">State Management with Redux Store</a>  </li>
<li><a class="post-section-overview" href="#heading-what-is-the-redux-store">What is the Redux Store?</a>  </li>
<li><a class="post-section-overview" href="#heading-store-structure-state-reducers-actions">Store Structure (State, Reducers, Actions)</a></li>
<li><a class="post-section-overview" href="#heading-actions-initiating-state-changes">Actions: Initiating State Changes</a>  </li>
<li><a class="post-section-overview" href="#heading-action-creators-functions-to-create-actions">Action Creators (Functions to Create Actions)</a>  </li>
<li><a class="post-section-overview" href="#heading-action-types-identifying-different-actions">Action Types (Identifying Different Actions)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-process-state-changes">How to Process State Changes</a>  </li>
<li><a class="post-section-overview" href="#heading-pure-functions-reducers-at-the-core">Pure Functions: Reducers at the Core</a>  </li>
<li><a class="post-section-overview" href="#heading-characteristics-of-pure-functions">Characteristics of Pure Functions</a> </li>
<li><a class="post-section-overview" href="#heading-anatomy-of-a-reducer-function">Anatomy of a Reducer Function</a>  </li>
<li><a class="post-section-overview" href="#heading-parameters-previous-state-and-action-object">Parameters: Previous State and Action Object</a>  </li>
<li><a class="post-section-overview" href="#heading-return-value-updated-state">Return Value: Updated State</a></li>
<li><a class="post-section-overview" href="#heading-how-to-handle-different-actions-in-reducers">How to Handle Different Actions in Reducers</a>  </li>
<li><a class="post-section-overview" href="#heading-using-switch-statements">Using Switch Statements or Conditional Logic</a></li>
<li><a class="post-section-overview" href="#heading-dispatching-actions-how-to-update-the-redux-store">Dispatching Actions: How to Update the Redux Store</a>  </li>
<li><a class="post-section-overview" href="#heading-the-dispatch-function">The <code>dispatch</code> Function</a>  </li>
<li><a class="post-section-overview" href="#heading-dispatching-actions-from-components-or-events">Dispatching Actions from Components or Events</a></li>
<li><a class="post-section-overview" href="#heading-how-to-access-specific-data-from-the-store">How to Access Specific Data from the Store</a>  </li>
<li><a class="post-section-overview" href="#heading-creating-selector-functions">Creating Selector Functions</a>  </li>
<li><a class="post-section-overview" href="#heading-memoization-for-efficient-selector-usage">Memoization for Efficient Selector Usage</a></li>
<li><a class="post-section-overview" href="#heading-how-to-connect-react-components-to-redux">How to Connect React Components to Redux</a>  </li>
<li><a class="post-section-overview" href="#heading-the-connect-function-from-react-redux-library">The <code>connect</code> Function from <code>react-redux</code> Library</a>  </li>
<li><a class="post-section-overview" href="#heading-mapping-state-and-dispatch-to-props">Mapping State and Dispatch to Props</a>  </li>
<li><a class="post-section-overview" href="#heading-using-connected-components-in-your-application">Using Connected Components in Your Application</a></li>
<li><a class="post-section-overview" href="#heading-advanced-redux-data-flow-techniques">Advanced Redux Data Flow Techniques</a>  </li>
<li><a class="post-section-overview" href="#heading-asynchronous-actions-redux-thunk-redux-saga">Asynchronous Actions (Redux Thunk, Redux Saga)</a>  </li>
<li><a class="post-section-overview" href="#heading-middleware-for-extending-redux-functionality">Middleware for Extending Redux Functionality</a></li>
<li><a class="post-section-overview" href="#heading-best-practices-for-managing-data-flow-in-redux">Best Practices for Managing Data Flow in Redux</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-what-is-redux">What is Redux?</h2>
<p>Redux is a predictable state container for JavaScript applications, primarily used with libraries like React. It helps manage the application state in a centralized store, making it easier to manage and update state across your entire application.</p>
<p>In simple terms, Redux provides a way to store and manage the data that your application needs to work. It follows a strict pattern to ensure that state changes are predictable and manageable.</p>
<h2 id="heading-why-use-redux-for-data-management">Why Use Redux for Data Management?</h2>
<p>Using Redux for data management in your application offers several advantages:</p>
<p><strong>Centralized State Management</strong>: Redux stores the application's state in a single store, making it easier to manage and debug compared to having scattered state across multiple components.</p>
<p><strong>Predictable State Changes</strong>: State mutations are done through reducers, which are pure functions. This ensures that state changes are predictable and traceable, making it easier to understand how data flows through your application.</p>
<p><strong>Easier Debugging</strong>: With a single source of truth, debugging becomes simpler. You can log state changes, track actions, and even implement time-travel debugging (via Redux DevTools) to replay actions and inspect state at any point in time.</p>
<p><strong>Facilitates Testing</strong>: Since reducers are pure functions that depend only on their input and produce predictable output, testing becomes straightforward. You can easily test how reducers update the state in response to different actions.</p>
<p><strong>Enforces Unidirectional Data Flow</strong>: Redux follows a strict unidirectional data flow pattern. Data flows in one direction: actions are dispatched, reducers update the state immutably, and components subscribe to the changes they're interested in. This pattern simplifies data management and reduces bugs related to inconsistent state.</p>
<p><strong>Eases State Persistence</strong>: Redux makes it easier to persist your application state across sessions or store it locally, enhancing the user experience by preserving data between visits.</p>
<p><strong>Scalability</strong>: Redux scales well with large applications because of its centralized state management. As your application grows, managing state becomes more manageable and less error-prone compared to using local component state or prop drilling.</p>
<h2 id="heading-core-concepts-of-redux-data-flow">Core Concepts of Redux Data Flow</h2>
<p>Understanding the core concepts of Redux data flow is essential for mastering state management in modern JavaScript applications.</p>
<h3 id="heading-unidirectional-data-flow">Unidirectional Data Flow</h3>
<p>Redux follows a strict unidirectional data flow pattern, which means that data in your application moves in a single direction through a series of steps:</p>
<ol>
<li><strong>Actions</strong>: Actions are plain JavaScript objects that represent an intention to change the state. They are the only source of information for the store.</li>
<li><strong>Reducers</strong>: Reducers are pure functions responsible for handling state transitions based on actions. They specify how the application's state changes in response to actions sent to the store.</li>
<li><strong>Store</strong>: The store holds the application state. It allows access to the state via <code>getState()</code>, updates the state via <code>dispatch(action)</code>, and registers listeners via <code>subscribe(listener)</code>.</li>
<li><strong>View</strong>: React components (or any other UI layer) subscribe to the store to receive updates when the state changes. They then re-render based on the updated state.</li>
</ol>
<p>Here’s a simplified overview of how the unidirectional data flow works in Redux:</p>
<ol>
<li><strong>Action Dispatch</strong>: Components dispatch actions to the Redux store using <code>store.dispatch(action)</code>. Actions are plain JavaScript objects with a <code>type</code> field that describes the type of action being performed.</li>
<li><strong>Action Handling</strong>: The store passes the dispatched action to the root reducer. The reducer is a pure function that takes the current state and the action, computes the new state based on the action, and returns the updated state.</li>
<li><strong>State Update</strong>: The Redux store updates its state based on the return value of the root reducer. It notifies all subscribed components of the state change.</li>
<li><strong>Component Re-render</strong>: Components that are subscribed to the store receive the updated state as props. They re-render with the new data.</li>
</ol>
<h3 id="heading-benefits-of-unidirectional-data-flow">Benefits of Unidirectional Data Flow</h3>
<p><strong>Predictability</strong>: By enforcing a single direction for data flow, Redux makes state changes more predictable and easier to understand. Actions are explicit about what changes are happening, and reducers clearly define how the state transitions occur.</p>
<p><strong>Debugging</strong>: Unidirectional data flow simplifies debugging because you can trace how state changes propagate through your application. Redux DevTools enhance this further by allowing you to track actions, inspect state changes over time, and even replay actions to reproduce bugs.</p>
<p><strong>Maintainability</strong>: With a clear separation between data (state) and logic (reducers), Redux promotes cleaner, more maintainable code. It reduces the likelihood of bugs caused by inconsistent state mutations or side effects.</p>
<p><strong>Scalability</strong>: As your application grows in size and complexity, unidirectional data flow helps manage state updates more effectively. It avoids the pitfalls of two-way data binding and ensures that changes to the state are controlled and manageable.</p>
<p><strong>Testing</strong>: Since reducers are pure functions that take inputs and produce outputs without side effects, unit testing becomes straightforward. You can test reducers with different actions and state scenarios to ensure they behave as expected.</p>
<h2 id="heading-state-management-with-redux-store">State Management with Redux Store</h2>
<p>State management plays a pivotal role in modern web development, ensuring applications maintain consistent and predictable states across various components.</p>
<h3 id="heading-what-is-the-redux-store">What is the Redux Store?</h3>
<p>The Redux Store is the heart of Redux state management. It holds the entire state tree of your application. The store allows you to:</p>
<ul>
<li>Access the current state of your application via <code>store.getState()</code>.</li>
<li>Dispatch actions to change the state using <code>store.dispatch(action)</code>.</li>
<li>Subscribe to changes in the state so your components can update accordingly using <code>store.subscribe(listener)</code>.</li>
</ul>
<p>In essence, the Redux Store acts as a centralized repository for the state of your application, facilitating predictable data flow and making state management more manageable.</p>
<h3 id="heading-store-structure-state-reducers-actions">Store Structure (State, Reducers, Actions)</h3>
<p>The <strong>state</strong> in Redux represents the entire state of your application. It is typically structured as a plain JavaScript object. The shape of the state is defined by the reducers. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">todos</span>: [],
  <span class="hljs-attr">visibilityFilter</span>: <span class="hljs-string">'SHOW_ALL'</span>,
};
</code></pre>
<p>In this example, <code>todos</code> and <code>visibilityFilter</code> are pieces of state managed by Redux.</p>
<p><strong>Reducers</strong> are functions that specify how the application's state changes in response to actions dispatched to the store. They take the current state and an action as arguments, and return the new state based on the action type. </p>
<p>Reducers must be pure functions, meaning they produce the same output for the same input and do not modify the state directly.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> todosReducer = <span class="hljs-function">(<span class="hljs-params">state = [], action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_TODO'</span>:
      <span class="hljs-keyword">return</span> [
        ...state,
        {
          <span class="hljs-attr">id</span>: action.id,
          <span class="hljs-attr">text</span>: action.text,
          <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
        }
      ];
    <span class="hljs-keyword">case</span> <span class="hljs-string">'TOGGLE_TODO'</span>:
      <span class="hljs-keyword">return</span> state.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
        (todo.id === action.id)
          ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
          : todo
      );
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example, <code>todosReducer</code> manages the <code>todos</code> piece of state, handling actions like <code>'ADD_TODO'</code> and <code>'TOGGLE_TODO'</code> to add new todos or toggle their completion status.</p>
<p><strong>Actions</strong> are plain JavaScript objects that describe what happened in your application. They are the only source of information for the store. Actions typically have a <code>type</code> field that indicates the type of action being performed, and they may also carry additional data necessary for the action.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> addTodo = <span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TODO'</span>,
  <span class="hljs-attr">id</span>: nextTodoId++,
  text
});

<span class="hljs-keyword">const</span> toggleTodo = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'TOGGLE_TODO'</span>,
  id
});
</code></pre>
<p>In this example, <code>addTodo</code> and <code>toggleTodo</code> are action creator functions that return actions to add a new todo and toggle the completion status of a todo, respectively.</p>
<p>The relationship between these elements in Redux is crucial for managing application state effectively:</p>
<ul>
<li><strong>Actions</strong> describe events that occur in your application.</li>
<li><strong>Reducers</strong> specify how the application's state changes in response to actions.</li>
<li><strong>Store</strong> holds the application state and allows you to dispatch actions to update the state.</li>
</ul>
<p>Together, these components form the core structure of Redux state management, providing a clear and predictable way to manage and update application state across your entire application.</p>
<h2 id="heading-actions-initiating-state-changes">Actions: Initiating State Changes</h2>
<p>Managing state effectively lies at the core of creating dynamic and responsive applications. Actions, within the Redux architecture and similar state management libraries, serve as important elements for initiating state changes.</p>
<h3 id="heading-action-creators-functions-to-create-actions">Action Creators (Functions to Create Actions)</h3>
<p>Action creators in Redux are functions that create and return action objects. These action objects describe what happened in your application and are dispatched to the Redux store to initiate state changes. </p>
<p>Action creators encapsulate the logic of creating actions, making your code more modular and easier to test.</p>
<p>Here's an example of an action creator:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Action creator function</span>
<span class="hljs-keyword">const</span> addTodo = <span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TODO'</span>,
  <span class="hljs-attr">id</span>: nextTodoId++,
  text
});

<span class="hljs-comment">// Usage of the action creator</span>
<span class="hljs-keyword">const</span> newTodoAction = addTodo(<span class="hljs-string">'Buy groceries'</span>);
</code></pre>
<p>In this example:</p>
<ul>
<li><code>addTodo</code> is an action creator function that takes <code>text</code> as a parameter and returns an action object.</li>
<li>The action object has a <code>type</code> field (<code>'ADD_TODO'</code>) that identifies the type of action and additional fields (<code>id</code> and <code>text</code>) that provide necessary data for the action.</li>
</ul>
<p>Action creators simplify the process of creating actions, especially when actions require complex data or calculations before dispatching.</p>
<h3 id="heading-action-types-identifying-different-actions">Action Types (Identifying Different Actions)</h3>
<p>Action types in Redux are string constants that define the type of action being performed. They are used to identify and differentiate different actions that can be dispatched to the Redux store. By using string constants for action types, Redux ensures that action types are unique and easy to reference throughout your application.</p>
<p>Here's how action types are typically defined:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Action types as constants</span>
<span class="hljs-keyword">const</span> ADD_TODO = <span class="hljs-string">'ADD_TODO'</span>;
<span class="hljs-keyword">const</span> TOGGLE_TODO = <span class="hljs-string">'TOGGLE_TODO'</span>;
<span class="hljs-keyword">const</span> SET_VISIBILITY_FILTER = <span class="hljs-string">'SET_VISIBILITY_FILTER'</span>;
</code></pre>
<p>These constants (<code>ADD_TODO</code>, <code>TOGGLE_TODO</code>, <code>SET_VISIBILITY_FILTER</code>) represent different actions that can occur in your application, such as adding a todo, toggling the completion status of a todo, or setting a visibility filter for todos.</p>
<p>Action types are typically used in action objects created by action creators and are matched in reducers to determine how the state should change in response to each action.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example of using action types in a reducer</span>
<span class="hljs-keyword">const</span> todosReducer = <span class="hljs-function">(<span class="hljs-params">state = [], action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> ADD_TODO:
      <span class="hljs-keyword">return</span> [
        ...state,
        {
          <span class="hljs-attr">id</span>: action.id,
          <span class="hljs-attr">text</span>: action.text,
          <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
        }
      ];
    <span class="hljs-keyword">case</span> TOGGLE_TODO:
      <span class="hljs-keyword">return</span> state.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
        (todo.id === action.id)
          ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
          : todo
      );
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li><code>ADD_TODO</code> and <code>TOGGLE_TODO</code> are action types used in the <code>todosReducer</code> to handle different types of actions (<code>'ADD_TODO'</code> and <code>'TOGGLE_TODO'</code>).</li>
<li>The <code>action.type</code> field in the switch statement ensures that the reducer responds appropriately to each dispatched action based on its type.</li>
</ul>
<h2 id="heading-how-to-process-state-changes">How to Process State Changes</h2>
<p>At the heart of state management are reducers, pure functions designed to handle state transitions in a controlled and immutable manner.</p>
<h3 id="heading-pure-functions-reducers-at-the-core">Pure Functions: Reducers at the Core</h3>
<p>Reducers in Redux are pure functions responsible for specifying how the application's state changes in response to actions dispatched to the store. They take the current state and an action as arguments, and return the new state based on the action type.</p>
<p>Here’s a breakdown of how reducers work and their role in managing state changes:</p>
<p><strong>Pure Functions</strong>: Reducers are pure functions, which means they:</p>
<ul>
<li>Produce the same output for the same input every time they are called.</li>
<li>Do not cause any side effects (such as modifying arguments or global variables).</li>
<li>Do not mutate the state directly, but instead return a new state object.</li>
</ul>
<p><strong>Handling State Transitions</strong>: Reducers specify how the application's state changes in response to different types of actions. They use the current state and the action dispatched to compute and return the new state.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example of a todos reducer</span>
<span class="hljs-keyword">const</span> todosReducer = <span class="hljs-function">(<span class="hljs-params">state = [], action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_TODO'</span>:
      <span class="hljs-keyword">return</span> [
        ...state,
        {
          <span class="hljs-attr">id</span>: action.id,
          <span class="hljs-attr">text</span>: action.text,
          <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
        }
      ];
    <span class="hljs-keyword">case</span> <span class="hljs-string">'TOGGLE_TODO'</span>:
      <span class="hljs-keyword">return</span> state.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
        (todo.id === action.id)
          ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
          : todo
      );
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li><code>todosReducer</code> is a pure function that takes <code>state</code> (current todos array) and <code>action</code> as arguments.</li>
<li>Depending on the <code>action.type</code>, it computes and returns a new state (updated todos array).</li>
</ul>
<p><strong>Immutable State Updates</strong>: Reducers should never mutate the state directly. Instead, they create copies of the state and modify the copies to produce a new state object. This ensures that Redux can detect state changes and update components efficiently.</p>
<p><strong>Single Responsibility Principle</strong>: Each reducer typically handles updates to a specific slice of the application state. This helps maintain a clear separation of concerns and makes reducers easier to understand, test, and maintain.</p>
<h3 id="heading-characteristics-of-pure-functions">Characteristics of Pure Functions</h3>
<p>Pure functions, including Redux reducers, have specific characteristics that make them well-suited for managing state changes:</p>
<p><strong>Deterministic</strong>: A pure function always produces the same output for the same input. This predictability ensures that reducers behave consistently and are easier to reason about.</p>
<p><strong>No Side Effects</strong>: Pure functions do not modify the input arguments or any external state. They only depend on their input parameters and produce an output without causing observable side effects.</p>
<p><strong>Immutable Data</strong>: Pure functions do not mutate data. Instead, they create and return new data structures. In Redux, reducers produce a new state object without modifying the existing state, enabling efficient change detection and state management.</p>
<p><strong>Referential Transparency</strong>: Pure functions can be replaced with their return values without affecting the correctness of the program. This property supports composability and makes it easier to test and reason about code.</p>
<h2 id="heading-anatomy-of-a-reducer-function">Anatomy of a Reducer Function</h2>
<p>A reducer function, at its core, defines how application state changes in response to dispatched actions. This function takes two parameters: the current state and an action object, determining the new state based on the type of action received.</p>
<h3 id="heading-parameters-previous-state-and-action-object">Parameters: Previous State and Action Object</h3>
<p>A reducer function in Redux is a pure function that takes two parameters: the previous state (state before the action is applied) and an action object. These parameters define how the reducer computes the next state of the application.</p>
<p><strong>Previous State</strong>: This parameter represents the current state of the application before the action is dispatched. It is immutable and should not be modified directly within the reducer.</p>
<p><strong>Action Object</strong>: An action object is a plain JavaScript object that describes what happened in your application. It typically has a <code>type</code> field that indicates the type of action being performed. Other fields in the action object may provide additional data necessary to update the state.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> action = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TODO'</span>,
  <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">text</span>: <span class="hljs-string">'Buy groceries'</span>
};
</code></pre>
<p>In this example, <code>action.type</code> is <code>'ADD_TODO'</code>, indicating that we want to add a new todo item to the state.</p>
<h3 id="heading-return-value-updated-state">Return Value: Updated State</h3>
<p>The reducer function must return the updated state based on the previous state and the action object passed to it. The updated state is typically a new object that represents the application's state after applying the action.</p>
<p>Here’s the basic structure of a reducer function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">todos</span>: [],
  <span class="hljs-attr">visibilityFilter</span>: <span class="hljs-string">'SHOW_ALL'</span>
};

<span class="hljs-keyword">const</span> todoAppReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_TODO'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: [
          ...state.todos,
          {
            <span class="hljs-attr">id</span>: action.id,
            <span class="hljs-attr">text</span>: action.text,
            <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
          }
        ]
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'TOGGLE_TODO'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: state.todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
          (todo.id === action.id)
            ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
            : todo
        )
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SET_VISIBILITY_FILTER'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">visibilityFilter</span>: action.filter
      };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li><code>todoAppReducer</code> is a reducer function that manages the state of todos and visibility filters.</li>
<li>It takes <code>state</code> (previous state) and <code>action</code> as parameters.</li>
<li>Depending on the <code>action.type</code>, it computes and returns a new state object that reflects the changes caused by the action.</li>
</ul>
<h3 id="heading-key-points">Key Points:</h3>
<p><strong>Immutable Update</strong>: Reducers should never modify the previous state directly. Instead, they create a new state object by copying the previous state (<code>...state</code>) and applying changes to it.</p>
<p><strong>Default Case</strong>: The <code>default</code> case in the <code>switch</code> statement returns the current state unchanged if the reducer doesn’t recognize the action type. This ensures that the reducer always returns a valid state object, even if no changes are made.</p>
<p><strong>Single Responsibility</strong>: Each case in the <code>switch</code> statement corresponds to a specific action type and is responsible for updating a specific slice of the application state. This promotes a clear separation of concerns and makes reducers easier to understand and maintain.</p>
<h2 id="heading-how-to-handle-different-actions-in-reducers">How to Handle Different Actions in Reducers</h2>
<p>In Redux, you can handle different actions in reducers using either switch statements or conditional logic. Both approaches aim to determine how the application state should change based on the type of action dispatched.</p>
<h3 id="heading-using-switch-statements">Using Switch Statements</h3>
<p>Switch statements are commonly used in Redux reducers to handle different action types. Each <code>case</code> in the switch statement corresponds to a specific action type, and the reducer executes the corresponding logic based on the action type.</p>
<p>Here's an example of using switch statements in a reducer:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">todos</span>: [],
  <span class="hljs-attr">visibilityFilter</span>: <span class="hljs-string">'SHOW_ALL'</span>
};

<span class="hljs-keyword">const</span> todoAppReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_TODO'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: [
          ...state.todos,
          {
            <span class="hljs-attr">id</span>: action.id,
            <span class="hljs-attr">text</span>: action.text,
            <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
          }
        ]
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'TOGGLE_TODO'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: state.todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
          (todo.id === action.id)
            ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
            : todo
        )
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SET_VISIBILITY_FILTER'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">visibilityFilter</span>: action.filter
      };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li>The <code>todoAppReducer</code> function uses a switch statement to handle different action types (<code>'ADD_TODO'</code>, <code>'TOGGLE_TODO'</code>, <code>'SET_VISIBILITY_FILTER'</code>).</li>
<li>Each <code>case</code> block specifies how the state should be updated in response to the corresponding action type.</li>
<li>The <code>default</code> case returns the current state unchanged if the reducer doesn’t recognize the action type, ensuring that the reducer always returns a valid state object.</li>
</ul>
<h3 id="heading-using-conditional-logic">Using Conditional Logic</h3>
<p>Alternatively, reducers can also use conditional logic (if-else statements) to determine how to update the state based on the action type. While less common than switch statements in Redux, conditional logic can be used similarly to handle actions.</p>
<p>Here's an example of using conditional logic in a reducer:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> todoAppReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'ADD_TODO'</span>) {
    <span class="hljs-keyword">return</span> {
      ...state,
      <span class="hljs-attr">todos</span>: [
        ...state.todos,
        {
          <span class="hljs-attr">id</span>: action.id,
          <span class="hljs-attr">text</span>: action.text,
          <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
        }
      ]
    };
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'TOGGLE_TODO'</span>) {
    <span class="hljs-keyword">return</span> {
      ...state,
      <span class="hljs-attr">todos</span>: state.todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
        (todo.id === action.id)
          ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed }
          : todo
      )
    };
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'SET_VISIBILITY_FILTER'</span>) {
    <span class="hljs-keyword">return</span> {
      ...state,
      <span class="hljs-attr">visibilityFilter</span>: action.filter
    };
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li>The <code>todoAppReducer</code> function uses if-else statements to check the action type (<code>action.type</code>) and execute different logic based on the type of action.</li>
<li>Each condition specifies how the state should be updated for the corresponding action type.</li>
<li>The final <code>else</code> block returns the current state unchanged if the action type is not recognized.</li>
</ul>
<h3 id="heading-choosing-between-switch-statements-and-conditional-logic">Choosing Between Switch Statements and Conditional Logic</h3>
<h4 id="heading-1-switch-statements">1. Switch Statements:</h4>
<ul>
<li>Advantages: Switch statements are typically more readable and maintainable when handling multiple action types in Redux reducers. They clearly separate different cases based on action types.</li>
<li>Considerations: Ensure each action type has a corresponding <code>case</code> in the switch statement to handle updates correctly.</li>
</ul>
<h4 id="heading-2-conditional-logic">2. Conditional Logic:</h4>
<ul>
<li>Advantages: Conditional logic (if-else statements) provides flexibility and can be easier to understand in certain scenarios where there are fewer action types.</li>
<li>Considerations: Maintain consistency in handling action types and ensure each condition handles state updates correctly.</li>
</ul>
<p>In practice, switch statements are the recommended approach in Redux reducers due to their clarity and convention within the Redux community. They help maintain a structured approach to managing state changes based on different action types, promoting consistency and predictability in Redux applications.</p>
<h2 id="heading-dispatching-actions-how-to-update-the-redux-store">Dispatching Actions: How to Update the Redux Store</h2>
<p>Dispatching actions in Redux is fundamental to managing state updates within your application. Redux, a predictable state container for JavaScript applications, relies on actions as payloads of information that send data from your application to the Redux store.</p>
<h3 id="heading-the-dispatch-function">The <code>dispatch</code> function</h3>
<p>In Redux, the <code>dispatch</code> function is a method provided by the Redux store. It is used to dispatch actions to trigger state changes in the application. When an action is dispatched, the Redux store calls the reducer function associated with it, computes the new state, and notifies all subscribers that the state has been updated.</p>
<p>Here's how you use the <code>dispatch</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-comment">// Reducer function</span>
<span class="hljs-keyword">const</span> counterReducer = <span class="hljs-function">(<span class="hljs-params">state = { count: <span class="hljs-number">0</span> }, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-comment">// Create Redux store</span>
<span class="hljs-keyword">const</span> store = createStore(counterReducer);

<span class="hljs-comment">// Dispatch actions to update state</span>
store.dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span> });
store.dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span> });
</code></pre>
<p>In this example:</p>
<ul>
<li>We create a Redux store using <code>createStore</code> and pass in the <code>counterReducer</code> function.</li>
<li>The <code>store.dispatch</code> function is used to dispatch actions (<code>{ type: 'INCREMENT' }</code> and <code>{ type: 'DECREMENT' }</code>) to update the state.</li>
<li>Each dispatched action triggers the corresponding case in the reducer, updating the state as defined.</li>
</ul>
<h3 id="heading-dispatching-actions-from-components-or-events">Dispatching Actions from Components or Events</h3>
<p>In a typical Redux application, actions are often dispatched from React components in response to user interactions or other events. </p>
<p>To dispatch actions from components, you typically connect the component to the Redux store using React Redux's <code>connect</code> function or hooks like <code>useDispatch</code>.</p>
<p>Here's how you can dispatch actions from a React component using <code>connect</code> and <code>mapDispatchToProps</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-comment">// Action creator functions</span>
<span class="hljs-keyword">const</span> increment = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span> });
<span class="hljs-keyword">const</span> decrement = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span> });

<span class="hljs-comment">// Component definition</span>
<span class="hljs-keyword">const</span> Counter = <span class="hljs-function">(<span class="hljs-params">{ count, increment, decrement }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{increment}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{decrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);

<span class="hljs-comment">// Map state to props</span>
<span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
  <span class="hljs-attr">count</span>: state.count
});

<span class="hljs-comment">// Map dispatch to props</span>
<span class="hljs-keyword">const</span> mapDispatchToProps = {
  increment,
  decrement
};

<span class="hljs-comment">// Connect component to Redux store</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(mapStateToProps, mapDispatchToProps)(Counter);
</code></pre>
<p>In this example:</p>
<ul>
<li><code>increment</code> and <code>decrement</code> are action creator functions that return actions (<code>{ type: 'INCREMENT' }</code> and <code>{ type: 'DECREMENT' }</code>).</li>
<li>The <code>Counter</code> component is connected to the Redux store using <code>connect</code>. It receives <code>count</code> from the Redux state as a prop, along with <code>increment</code> and <code>decrement</code> action creators.</li>
<li>Clicking the "Increment" and "Decrement" buttons dispatches actions, which are handled by the reducer to update the Redux state.</li>
</ul>
<p>Alternatively, you can use React Redux hooks (<code>useDispatch</code>) for dispatching actions in functional components:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch, useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-keyword">const</span> Counter = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> count = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.count);
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">const</span> handleIncrement = <span class="hljs-function">() =&gt;</span> {
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span> });
  };

  <span class="hljs-keyword">const</span> handleDecrement = <span class="hljs-function">() =&gt;</span> {
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span> });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleIncrement}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDecrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Counter;
</code></pre>
<p>In this functional component example:</p>
<ul>
<li><code>useSelector</code> is used to select <code>count</code> from the Redux store state.</li>
<li><code>useDispatch</code> is used to get the <code>dispatch</code> function from the Redux store.</li>
<li><code>handleIncrement</code> and <code>handleDecrement</code> functions dispatch actions (<code>{ type: 'INCREMENT' }</code> and <code>{ type: 'DECREMENT' }</code>) to update the Redux state when the buttons are clicked.</li>
</ul>
<h2 id="heading-how-to-access-specific-data-from-the-store">How to Access Specific Data from the Store</h2>
<p>Accessing specific data from the store in Redux involves navigating through the application's state structure to retrieve precise information needed for rendering components or performing logic.</p>
<h3 id="heading-creating-selector-functions">Creating Selector Functions</h3>
<p>Selectors in Redux are functions that encapsulate the logic for retrieving specific pieces of data from the Redux store state. They help to decouple the components from the structure of the state and facilitate efficient data access and transformation.</p>
<p>Here’s how you can create selector functions:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example Redux state</span>
<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">todos</span>: [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Learn Redux'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Write Redux selectors'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">true</span> },
    <span class="hljs-comment">// more todos...</span>
  ],
  <span class="hljs-attr">visibilityFilter</span>: <span class="hljs-string">'SHOW_COMPLETED'</span>
};

<span class="hljs-comment">// Selector function to get todos from state</span>
<span class="hljs-keyword">const</span> getTodos = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos;

<span class="hljs-comment">// Selector function to filter todos based on visibility filter</span>
<span class="hljs-keyword">const</span> getVisibleTodos = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> todos = getTodos(state);
  <span class="hljs-keyword">const</span> visibilityFilter = state.visibilityFilter;

  <span class="hljs-keyword">switch</span> (visibilityFilter) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_COMPLETED'</span>:
      <span class="hljs-keyword">return</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> todo.completed);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ACTIVE'</span>:
      <span class="hljs-keyword">return</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> !todo.completed);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ALL'</span>:
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> todos;
  }
};
</code></pre>
<p>In this example:</p>
<ul>
<li><code>getTodos</code> is a selector function that retrieves the <code>todos</code> array from the Redux state.</li>
<li><code>getVisibleTodos</code> is a selector function that filters <code>todos</code> based on the <code>visibilityFilter</code> stored in the state.</li>
</ul>
<p>Selectors can also be composed to create more complex selectors:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Composed selector function to get visible todos</span>
<span class="hljs-keyword">const</span> getVisibleTodos = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> todos = getTodos(state);
  <span class="hljs-keyword">const</span> visibilityFilter = state.visibilityFilter;

  <span class="hljs-keyword">switch</span> (visibilityFilter) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_COMPLETED'</span>:
      <span class="hljs-keyword">return</span> getCompletedTodos(todos);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ACTIVE'</span>:
      <span class="hljs-keyword">return</span> getActiveTodos(todos);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ALL'</span>:
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> todos;
  }
};

<span class="hljs-comment">// Helper functions for filtering todos</span>
<span class="hljs-keyword">const</span> getCompletedTodos = <span class="hljs-function">(<span class="hljs-params">todos</span>) =&gt;</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> todo.completed);
<span class="hljs-keyword">const</span> getActiveTodos = <span class="hljs-function">(<span class="hljs-params">todos</span>) =&gt;</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> !todo.completed);
</code></pre>
<h3 id="heading-memoization-for-efficient-selector-usage">Memoization for Efficient Selector Usage</h3>
<p>Memoization is a technique used to optimize expensive computations by caching the results of function calls based on their input. In the context of Redux selectors, memoization can improve performance by ensuring that selectors only recalculate their results when their input (state) changes.</p>
<p>You can use libraries like <code>reselect</code> for memoization in Redux selectors:</p>
<pre><code class="lang-bash">npm install reselect
</code></pre>
<p>Example usage of <code>reselect</code> for memoization:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'reselect'</span>;

<span class="hljs-comment">// Selectors</span>
<span class="hljs-keyword">const</span> getTodos = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos;
<span class="hljs-keyword">const</span> getVisibilityFilter = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.visibilityFilter;

<span class="hljs-comment">// Memoized selector to get visible todos</span>
<span class="hljs-keyword">const</span> getVisibleTodos = createSelector(
  [getTodos, getVisibilityFilter],
  <span class="hljs-function">(<span class="hljs-params">todos, visibilityFilter</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (visibilityFilter) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_COMPLETED'</span>:
        <span class="hljs-keyword">return</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> todo.completed);
      <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ACTIVE'</span>:
        <span class="hljs-keyword">return</span> todos.filter(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> !todo.completed);
      <span class="hljs-keyword">case</span> <span class="hljs-string">'SHOW_ALL'</span>:
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> todos;
    }
  }
);
</code></pre>
<p>In this example:</p>
<ul>
<li><code>createSelector</code> from <code>reselect</code> creates a memoized selector that takes <code>getTodos</code> and <code>getVisibilityFilter</code> as input selectors.</li>
<li>The selector function computes the filtered todos based on the <code>visibilityFilter</code> and caches the result until the input selectors change.</li>
</ul>
<h2 id="heading-how-to-connect-react-components-to-redux">How to Connect React Components to Redux</h2>
<p>Connecting React components to Redux is a fundamental technique for managing application state efficiently within React-based projects. Redux serves as a centralized store that holds the entire state of your application, making it accessible to any component that needs it.</p>
<h3 id="heading-the-connect-function-from-react-redux-library">The <code>connect</code> Function from react-redux Library</h3>
<p>In React applications using Redux for state management, the <code>connect</code> function from the <code>react-redux</code> library is used to connect React components to the Redux store. It provides a way to inject Redux state and action dispatching functions (dispatchers) into your components.</p>
<p>Here’s how you use <code>connect</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-comment">// Define a React component</span>
<span class="hljs-keyword">const</span> Counter = <span class="hljs-function">(<span class="hljs-params">{ count, increment, decrement }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{increment}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{decrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);

<span class="hljs-comment">// Map Redux state to component props</span>
<span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({
  <span class="hljs-attr">count</span>: state.count
});

<span class="hljs-comment">// Map dispatching actions to component props</span>
<span class="hljs-keyword">const</span> mapDispatchToProps = {
  <span class="hljs-attr">increment</span>: <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span> }),
  <span class="hljs-attr">decrement</span>: <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span> })
};

<span class="hljs-comment">// Connect component to Redux store</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(mapStateToProps, mapDispatchToProps)(Counter);
</code></pre>
<h3 id="heading-mapping-state-and-dispatch-to-props">Mapping State and Dispatch to Props</h3>
<p><strong><code>mapStateToProps</code></strong>: This function maps the Redux store's state to the props of your React component. It takes the Redux state as an argument and returns an object. Each field in the returned object will become a prop for the connected component.</p>
<p><strong><code>mapDispatchToProps</code></strong>: This function maps dispatching actions to props of your React component. It can be an object where each field is an action creator function, or a function that receives <code>dispatch</code> as an argument and returns an object. Each action creator will be wrapped automatically with <code>dispatch</code> so they can be called directly.</p>
<p>In the example:</p>
<ul>
<li><code>mapStateToProps</code> maps the <code>count</code> field from the Redux state (<code>state.count</code>) to the <code>count</code> prop of the <code>Counter</code> component.</li>
<li><code>mapDispatchToProps</code> maps the <code>increment</code> and <code>decrement</code> actions to props, so clicking the buttons in the <code>Counter</code> component will dispatch the corresponding actions (<code>{ type: 'INCREMENT' }</code> and <code>{ type: 'DECREMENT' }</code>).</li>
</ul>
<h3 id="heading-using-connected-components-in-your-application">Using Connected Components in Your Application</h3>
<p>Once a component is connected to the Redux store using <code>connect</code>, it can access Redux state and dispatch actions via props. Here’s how you can use connected components in your application:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>; <span class="hljs-comment">// Import your root reducer</span>
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>; <span class="hljs-comment">// Import your connected component</span>

<span class="hljs-comment">// Create Redux store with root reducer</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer);

<span class="hljs-comment">// Render the App component inside the Provider</span>
ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>In this setup:</p>
<ul>
<li><code>Provider</code> is a component from <code>react-redux</code> that makes the Redux store available to any nested components that have been connected using <code>connect</code>.</li>
<li><code>store</code> is created using <code>createStore</code> and combined with a root reducer (<code>rootReducer</code>) that combines all your reducers into one.</li>
</ul>
<p>By wrapping your top-level component (<code>App</code> in this case) with <code>Provider</code> and passing the Redux store as a prop, all connected components within your application can access the Redux store and interact with it through props (<code>mapStateToProps</code> and <code>mapDispatchToProps</code> mappings).</p>
<h2 id="heading-advanced-redux-data-flow-techniques">Advanced Redux Data Flow Techniques</h2>
<p>Advanced Redux data flow techniques expand upon the fundamental principles of managing state in complex applications. These techniques go beyond basic actions and reducers, introducing concepts such as middleware, selectors, and asynchronous actions.</p>
<h3 id="heading-asynchronous-actions-redux-thunk-redux-saga">Asynchronous Actions (Redux Thunk, Redux Saga)</h3>
<p>In Redux, handling asynchronous actions involves managing actions that have side effects, such as fetching data from a server or updating state asynchronously. Redux provides several middleware solutions to handle asynchronous actions effectively.</p>
<h4 id="heading-redux-thunk">Redux Thunk</h4>
<p>Redux Thunk is a middleware that allows you to write action creators that return a function instead of an action object. This function can then perform asynchronous operations and dispatch regular synchronous actions when the asynchronous operations complete.</p>
<p>Example of using Redux Thunk for asynchronous actions:</p>
<p><strong>Setting up Redux Thunk Middleware</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>; <span class="hljs-comment">// Import your root reducer</span>

<span class="hljs-comment">// Create Redux store with thunk middleware</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(thunk));
</code></pre>
<p><strong>Async Action Creator using Redux Thunk</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Action creator function using Redux Thunk</span>
<span class="hljs-keyword">const</span> fetchPosts = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_REQUEST'</span> });

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);
      <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> response.json();
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_SUCCESS'</span>, <span class="hljs-attr">payload</span>: posts });
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_FAILURE'</span>, <span class="hljs-attr">error</span>: error.message });
    }
  };
};
</code></pre>
<p>In this example:</p>
<ul>
<li><code>fetchPosts</code> is an action creator that returns a function instead of an action object.</li>
<li>Inside the function, you can perform asynchronous operations (like fetching data) and dispatch actions based on the result.</li>
<li>Redux Thunk middleware intercepts functions returned by action creators, enabling asynchronous actions in Redux.</li>
</ul>
<h4 id="heading-redux-saga">Redux Saga</h4>
<p>Redux Saga is another middleware for handling side effects in Redux applications. It uses ES6 generators to make asynchronous code easier to read, write, and test.</p>
<p>Example of using Redux Saga for handling asynchronous actions:</p>
<p><strong>Setting up Redux Saga Middleware</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> createSagaMiddleware <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-saga'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>; <span class="hljs-comment">// Import your root reducer</span>
<span class="hljs-keyword">import</span> rootSaga <span class="hljs-keyword">from</span> <span class="hljs-string">'./sagas'</span>; <span class="hljs-comment">// Import your root saga</span>

<span class="hljs-comment">// Create Redux Saga middleware</span>
<span class="hljs-keyword">const</span> sagaMiddleware = createSagaMiddleware();

<span class="hljs-comment">// Create Redux store with Saga middleware</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(sagaMiddleware));

<span class="hljs-comment">// Run the root saga</span>
sagaMiddleware.run(rootSaga);
</code></pre>
<p><strong>Example Saga (rootSaga.js)</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { all, call, put, takeEvery } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-saga/effects'</span>;
<span class="hljs-keyword">import</span> { fetchPostsSuccess, fetchPostsFailure } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>; <span class="hljs-comment">// Import your action creators</span>

<span class="hljs-comment">// Worker saga for fetching posts</span>
<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">fetchPostsSaga</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">yield</span> call(fetch, <span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);
    <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">yield</span> call([response, <span class="hljs-string">'json'</span>]);
    <span class="hljs-keyword">yield</span> put(fetchPostsSuccess(posts));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">yield</span> put(fetchPostsFailure(error.message));
  }
}

<span class="hljs-comment">// Watcher saga to listen for FETCH_POSTS_REQUEST action</span>
<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watchFetchPosts</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> takeEvery(<span class="hljs-string">'FETCH_POSTS_REQUEST'</span>, fetchPostsSaga);
}

<span class="hljs-comment">// Root saga</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">rootSaga</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> all([
    watchFetchPosts()
    <span class="hljs-comment">// Add more watchers if needed</span>
  ]);
}
</code></pre>
<p>In this example:</p>
<ul>
<li><code>fetchPostsSaga</code> is a worker saga that performs the asynchronous operation (fetching posts).</li>
<li><code>watchFetchPosts</code> is a watcher saga that listens for specific actions (<code>FETCH_POSTS_REQUEST</code>) and triggers the corresponding worker saga.</li>
<li><code>rootSaga</code> combines multiple sagas using <code>all</code> and runs them using <code>sagaMiddleware.run</code>.</li>
</ul>
<h3 id="heading-middleware-for-extending-redux-functionality">Middleware for Extending Redux Functionality</h3>
<p>Middleware in Redux provides a way to extend the Redux store's capabilities, such as logging actions, handling asynchronous operations, routing, and more. Middleware sits between dispatching an action and the moment it reaches the reducer, allowing interception and manipulation of actions.</p>
<h4 id="heading-example-of-custom-middleware">Example of Custom Middleware:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function"><span class="hljs-params">store</span> =&gt;</span> <span class="hljs-function"><span class="hljs-params">next</span> =&gt;</span> <span class="hljs-function"><span class="hljs-params">action</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Dispatching action:'</span>, action);
  <span class="hljs-keyword">const</span> result = next(action);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'New state:'</span>, store.getState());
  <span class="hljs-keyword">return</span> result;
};

<span class="hljs-comment">// Applying custom middleware to Redux store</span>
<span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>; <span class="hljs-comment">// Import your root reducer</span>

<span class="hljs-comment">// Create Redux store with custom middleware</span>
<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(loggerMiddleware));
</code></pre>
<p>In this example:</p>
<ul>
<li><code>loggerMiddleware</code> is a custom middleware function that logs each dispatched action and the resulting state.</li>
<li><code>next</code> is a function provided by Redux that allows the action to continue to the next middleware or the reducer.</li>
<li>Custom middleware enhances Redux functionality by intercepting actions, performing custom logic, and optionally dispatching new actions or modifying existing ones.</li>
</ul>
<h2 id="heading-best-practices-for-managing-data-flow-in-redux">Best Practices for Managing Data Flow in Redux</h2>
<p>Redux provides a structured way to manage state in JavaScript applications, but effective usage requires adhering to best practices. Here are my key recommendations for managing data flow in Redux:</p>
<h3 id="heading-organizing-reducers-and-actions">Organizing Reducers and Actions</h3>
<p><strong>File Structure and Organization</strong>:</p>
<ul>
<li><strong>Separate concerns</strong>: Keep actions, reducers, and selectors in separate files to maintain clarity and modularity.</li>
<li><strong>Feature-based structure</strong>: Group related actions and reducers together based on features rather than types.</li>
</ul>
<pre><code class="lang-plaintext">src/
├── actions/
│   ├── todosActions.js
│   └── userActions.js
├── reducers/
│   ├── todosReducer.js
│   └── userReducer.js
├── selectors/
│   ├── todosSelectors.js
│   └── userSelectors.js
└── store.js
</code></pre>
<p><strong>Action Types</strong>:</p>
<ul>
<li><strong>Constants</strong>: Use constants or enums for action types to prevent typos and ensure consistency.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Action types</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD_TODO = <span class="hljs-string">'ADD_TODO'</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DELETE_TODO = <span class="hljs-string">'DELETE_TODO'</span>;
</code></pre>
<p><strong>Reducer Composition</strong>:</p>
<ul>
<li><strong>Combine reducers</strong>: Use <code>combineReducers</code> from Redux to combine multiple reducers into a single root reducer.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> todosReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./todosReducer'</span>;
<span class="hljs-keyword">import</span> userReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./userReducer'</span>;

<span class="hljs-keyword">const</span> rootReducer = combineReducers({
  <span class="hljs-attr">todos</span>: todosReducer,
  <span class="hljs-attr">user</span>: userReducer
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> rootReducer;
</code></pre>
<h3 id="heading-immutable-state-updates">Immutable State Updates</h3>
<p><strong>Immutability with Spread Operator</strong>:</p>
<ul>
<li><strong>Use spread operator (<code>...</code>)</strong>: Create new objects or arrays when updating state to maintain immutability.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Updating an array in Redux state</span>
<span class="hljs-keyword">const</span> todosReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> ADD_TODO:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: [
          ...state.todos,
          {
            <span class="hljs-attr">id</span>: action.id,
            <span class="hljs-attr">text</span>: action.text,
            <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
          }
        ]
      };
    <span class="hljs-keyword">case</span> TOGGLE_TODO:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">todos</span>: state.todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
          (todo.id === action.id) ? { ...todo, <span class="hljs-attr">completed</span>: !todo.completed } : todo
        )
      };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p><strong>Immutable Libraries</strong>:</p>
<ul>
<li><strong>Immutable.js</strong>: Consider using libraries like Immutable.js for more complex data structures to enforce immutability and optimize performance.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { <span class="hljs-built_in">Map</span>, List } <span class="hljs-keyword">from</span> <span class="hljs-string">'immutable'</span>;

<span class="hljs-keyword">const</span> initialState = <span class="hljs-built_in">Map</span>({
  <span class="hljs-attr">todos</span>: List(),
  <span class="hljs-attr">user</span>: <span class="hljs-built_in">Map</span>()
});

<span class="hljs-keyword">const</span> todosReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> ADD_TODO:
      <span class="hljs-keyword">return</span> state.update(<span class="hljs-string">'todos'</span>, <span class="hljs-function"><span class="hljs-params">todos</span> =&gt;</span> todos.push(<span class="hljs-built_in">Map</span>({
        <span class="hljs-attr">id</span>: action.id,
        <span class="hljs-attr">text</span>: action.text,
        <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
      })));

    <span class="hljs-keyword">case</span> TOGGLE_TODO:
      <span class="hljs-keyword">return</span> state.update(<span class="hljs-string">'todos'</span>, <span class="hljs-function"><span class="hljs-params">todos</span> =&gt;</span>
        todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span>
          (todo.get(<span class="hljs-string">'id'</span>) === action.id) ? todo.set(<span class="hljs-string">'completed'</span>, !todo.get(<span class="hljs-string">'completed'</span>)) : todo
        )
      );

    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<h3 id="heading-testing-redux-applications">Testing Redux Applications</h3>
<p><strong>Unit Testing</strong>:</p>
<ul>
<li><strong>Reducers</strong>: Test reducers to ensure they handle actions correctly and return the expected state.</li>
</ul>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'todosReducer'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should handle ADD_TODO'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> action = { <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TODO'</span>, <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Test todo'</span> };
    <span class="hljs-keyword">const</span> initialState = { <span class="hljs-attr">todos</span>: [] };
    <span class="hljs-keyword">const</span> expectedState = { <span class="hljs-attr">todos</span>: [{ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Test todo'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> }] };

    expect(todosReducer(initialState, action)).toEqual(expectedState);
  });
});
</code></pre>
<p><strong>Integration Testing</strong>:</p>
<ul>
<li><strong>Action Creators and Thunks</strong>: Test action creators and thunks to verify they dispatch the correct actions or handle asynchronous operations.</li>
</ul>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'fetchPosts action creator'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'creates FETCH_POSTS_SUCCESS when fetching posts has been done'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> expectedActions = [
      { <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_REQUEST'</span> },
      { <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_SUCCESS'</span>, <span class="hljs-attr">payload</span>: { <span class="hljs-comment">/* mocked data */</span> } }
    ];

    <span class="hljs-keyword">const</span> store = mockStore({ <span class="hljs-attr">posts</span>: [] });

    <span class="hljs-keyword">return</span> store.dispatch(fetchPosts()).then(<span class="hljs-function">() =&gt;</span> {
      expect(store.getActions()).toEqual(expectedActions);
    });
  });
});
</code></pre>
<p><strong>Integration with Components</strong>:</p>
<ul>
<li><strong>Connected Components</strong>: Test connected components using <code>redux-mock-store</code> to simulate Redux store behavior.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> configureStore <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-mock-store'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

<span class="hljs-keyword">const</span> mockStore = configureStore([]);

describe(<span class="hljs-string">'&lt;App /&gt;'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'renders App component'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> store = mockStore({ <span class="hljs-comment">/* mocked state */</span> });

    <span class="hljs-keyword">const</span> { getByText } = render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
    );

    expect(getByText(<span class="hljs-string">'Welcome to Redux App'</span>)).toBeInTheDocument();
  });
});
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Redux offers a powerful state management solution for JavaScript applications, providing a predictable and centralized way to manage application state. </p>
<p>Whether handling asynchronous operations with middleware like Redux Thunk or Redux Saga, or optimizing state management through immutable data practices, Redux empowers you to build scalable and maintainable applications. </p>
<p>By mastering these techniques, you can leverage Redux to streamline data flow, enhance application performance, and simplify the complexities of managing state in modern web development.</p>
<p>That's all for this article! If you'd like to continue the conversation or have questions, suggestions, or feedback, feel free to reach out to connect with me on <a target="_blank" href="https://ng.linkedin.com/in/joan-ayebola">LinkedIn</a>. And if you enjoyed this content, consider <a target="_blank" href="https://www.buymeacoffee.com/joanayebola">buying me a coffee</a> to support the creation of more developer-friendly contents.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React State vs Refs – Differences and Use Cases ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll delve into a thorough comparison of React state and refs, exploring their suitability for specific scenarios. When faced with the need to store data in your React application, the first question that comes to mind is: "Will the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-state-vs-ref-differences-and-use-cases/</link>
                <guid isPermaLink="false">66ba292c2984e390eea7b654</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 11 Apr 2024 13:07:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/STATE-VS-REF.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll delve into a thorough comparison of React <code>state</code> and <code>refs</code>, exploring their suitability for specific scenarios.</p>
<p>When faced with the need to store data in your React application, the first question that comes to mind is: "Will the data change at some point during the component's lifecycle?" If it won't, a regular <code>const</code> variable is well-suited. </p>
<p>However, if the data will change, then that is where the <code>useState</code> and <code>useRef</code> hooks comes in.</p>
<h2 id="heading-understanding-the-usestate-and-useref-hooks">Understanding the useState and useRef Hooks</h2>
<h3 id="heading-usestate-hook">useState Hook</h3>
<p>The <code>useState</code> hook is designed to manage a component's state, which represents data that can change over time and is important for the component to render. You can add state to your component by importing the <code>useState</code> hook from React.</p>
<pre><code class="lang-react">import { useState } from 'react';
</code></pre>
<p>The <code>useState</code> hook is usually initialized with an initial value and returns an array of a declared state variable and its associated setter function. It looks something like this:</p>
<pre><code class="lang-react">import { useState } from "react";

function App() {
  const [count, setCount] = useState(0); //declared useState hook

  return (
    &lt;&gt;
      &lt;h1&gt;State example&lt;/h1&gt;
      &lt;div&gt;
        &lt;button onClick={() =&gt; setCount((count) =&gt; count + 1)}&gt;
          count is {count}
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}
export default App;
</code></pre>
<p>In the above code,</p>
<ol>
<li>The <code>useState</code> is initialized with a value of zero and returns a <code>count</code> variable and <code>setCount</code> setter function.</li>
<li>The <code>count</code> variable is set dynamically by the <code>setCount</code> setter function that increments the <code>count</code> by 1. </li>
<li>For each click of the button, the <code>App</code> component is re-rendered and the updated value is displayed within the button text.</li>
</ol>
<p>Having a good understanding of React state is important as it is one of the most used concept. You can have a more in-depth read on states here: <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/">State Management in React</a>.</p>
<h3 id="heading-useref-hook">useRef Hook</h3>
<p>The <code>useRef</code> hook  is used to create refs in React components. A ref is an object with a <code>current</code> property that holds a value. It basically references a DOM element or an instance of a component. We can read and update the value by accessing the current property.</p>
<pre><code class="lang-react">const ref = useRef(initialValue)

ref.current = initialValue
</code></pre>
<p>Here, is a full code snippet of ref in action:</p>
<pre><code class="lang-react">import { useRef } from "react";

function App() {
  let ref = useRef(0); 

  function handleIncrease() {
    ref.current++;
    alert(`You have clicked it ${ref.current} times`);
  }
  return (
    &lt;&gt;
      &lt;h1&gt;Ref example&lt;/h1&gt;
      &lt;div&gt;
        &lt;button onClick={handleIncrease}&gt;Click Me&lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;
</code></pre>
<p>Let's break it down:</p>
<ol>
<li>We imported <code>useRef</code> from React.</li>
<li>In our <code>App</code> component, we declared a <code>ref</code> object with the initial value set to zero.</li>
<li><code>handleIncrease</code> is our handler function that increments the <code>ref.current</code> value by 1 and then alerts the user of the current value.</li>
<li>In our <code>App</code> component's JSX, we have a button with an <code>onClick</code> prop and the <code>handleIncrease</code> handler function passed to it.</li>
</ol>
<p>Having understood how the two hooks work, we'll go ahead to compare and explore when they would be suitable to use.</p>
<h2 id="heading-react-state-vs-ref">React State vs Ref</h2>
<h3 id="heading-render-trigger">Render Trigger</h3>
<p>In React, states always trigger a re-render due to a mechanism known as <code>reconciliation</code> – which updates the user interface based on changes made to the state or props. </p>
<p>Under the hood, React compares the new state to the previous and computes the minimal changes needed to update the user interface that reflects the new state. This process ensures consistency with the changed state or props.</p>
<p>On the flip side, refs do not trigger a re-render when changes are made to it. Refs are not directly linked to the component's rendering cycle. </p>
<p>Therefore, if you want a consistent user interface that reacts to data changes, it is advisable to use states. Refs are better used for managing mutable values without affecting the user interface.</p>
<h3 id="heading-mutability">Mutability</h3>
<p>React state cannot be directly changed once it has been set because the setter function updates of the state variable. By using this approach, React maintains the predictability and stability of the data flow. This also helps in making debugging easier.</p>
<p>Conversely, refs are mutable as you can modify the <code>ref current</code> value outside of the rendering process. Values can be changed at any point unlike states – refs do not have an updater function. </p>
<h3 id="heading-readwrite-operations">Read/Write Operations</h3>
<p>The <code>useState</code> hook setter function allows you to update the state value. For instance:</p>
<pre><code class="lang-react">const [state, setState] = useState(false)
function handleOpposite(){
    setState(!state)
 }
</code></pre>
<p>In this code, we can see that:</p>
<ol>
<li>The initial value is set to a boolean value of <code>false</code>.</li>
<li>The <code>handleOpposite</code> function is negating the boolean value of the <code>state</code>  and the <code>setState</code> houses the updated value of <code>true</code> .</li>
</ol>
<p>In this simple operation,</p>
<ol>
<li>An implicit <strong>read</strong> operation has been done as the initial value had to be accessed before the negation.</li>
<li>A <strong>write</strong> operation occurred when the negation (!) was used on the initial value, which changed the value to the opposite.</li>
</ol>
<p>An explicit <strong>read</strong> operation of state happens when you simply access the state variable directly within a component's JSX. For instance:</p>
<pre><code>&lt;button onClick={<span class="hljs-function">() =&gt;</span> setCount(<span class="hljs-function">(<span class="hljs-params">count</span>) =&gt;</span> count + <span class="hljs-number">1</span>)}&gt;
  count is {count}
 &lt;/button&gt;
</code></pre><p>The <code>{count}</code> is the currently accessed value of the state and would be displayed on the UI accordingly.</p>
<p>On the other hand, accessing or modifying a <code>ref</code>'s current value during rendering can interfere with React's reconciliation process, potentially causing inconsistencies between the virtual DOM and the actual DOM. </p>
<p>In order to ensure predictable behavior and optimal performance in components, it's best to adhere to React's guidelines and avoid either accessing or modifying refs during rendering.</p>
<h3 id="heading-persisting-across-renders">Persisting Across Renders</h3>
<p>Data persistence across renders in React means that data remains consistent and available between different render cycles of a component. When data is persisted, it remains unchanged and accessible after re-rendering. State and Ref both persist data across renders.</p>
<p>Persistence is crucial for maintaining the integrity of the application's state and ensures that components operate as expected. </p>
<h3 id="heading-asynchronous-updates">Asynchronous Updates</h3>
<p>Updates in React state are asynchronous which means that when there is a request for an update, there is a possibility that the updates will not be executed immediately. React might leave some state changes for later while updating other components in one go!</p>
<p>Ref updates are done synchronously where tasks are performed in a sequential manner. Each task waits for the previous one to finish before starting, ensuring that they are executed in a predictable and deterministic manner.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we looked extensively at the hooks — <code>useState</code> and <code>useRef</code> — that handle dynamic data (data that will change) in React applications. </p>
<p>We compared both hooks and at this point, you should be know their similarities, differences, when and where they are best suited.</p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> for front-end related discussions and posts. See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Work with Redux-Thunk – Explained with Examples ]]>
                </title>
                <description>
                    <![CDATA[ Redux has become the go-to state management library for many JavaScript applications due to its predictable state container and unidirectional data flow. However, handling asynchronous actions in Redux can be a bit tricky. That's where Redux middlewa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-work-with-redux-thunk/</link>
                <guid isPermaLink="false">66c4c3ee1b22d2d8d9040ead</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Mon, 26 Feb 2024 02:35:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--11-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Redux has become the go-to state management library for many JavaScript applications due to its predictable state container and unidirectional data flow.</p>
<p>However, handling asynchronous actions in Redux can be a bit tricky. That's where Redux middleware like Redux-Thunk comes to the rescue.</p>
<p>In essence, Redux-Thunk enhances the capabilities of Redux by providing a straightforward and efficient mechanism for managing asynchronous actions. It enables developers to write clean, predictable, and maintainable code while ensuring the integrity of the application's state management.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-1-introduction-to-redux-thunk">Introduction to Redux-Thunk</a></p>
</li>
<li><p>1.1. <a class="post-section-overview" href="#heading-11-understanding-middleware-in-redux">Understanding Middleware in Redux</a></p>
</li>
<li><p>1.2. <a class="post-section-overview" href="#heading-12-the-role-of-redux-thunk">The Role of Redux-Thunk</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-installation-and-setup">Installation and Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-working-with-redux-thunk">Working with Redux-Thunk</a></p>
</li>
<li><p>3.1. <a class="post-section-overview" href="#heading-31-writing-thunk-functions">Writing Thunk Functions</a></p>
</li>
<li><p>3.2. <a class="post-section-overview" href="#heading-32-dispatching-thunk-actions">Dispatching Thunk Actions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-handling-asynchronous-operations">Handling Asynchronous Operations</a></p>
</li>
<li><p>4.1. <a class="post-section-overview" href="#heading-41-making-asynchronous-api-calls">Making Asynchronous API Calls</a></p>
</li>
<li><p>4.2. <a class="post-section-overview" href="#heading-42-managing-side-effects-with-thunks">Managing Side Effects with Thunks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-advanced-techniques">Advanced Techniques</a></p>
</li>
<li><p>5.1. <a class="post-section-overview" href="#heading-51-error-handling-in-thunks">Error Handling in Thunks</a></p>
</li>
<li><p>5.2. <a class="post-section-overview" href="#heading-52-chaining-multiple-thunks">Chaining Multiple Thunks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-best-practices">Best Practices</a></p>
</li>
<li><p>6.1. <a class="post-section-overview" href="#heading-61-structuring-thunks-for-maintainability">Structuring Thunks for Maintainability</a></p>
</li>
<li>6.2. <a class="post-section-overview" href="#heading-62-avoiding-common-pitfalls">Avoiding Common Pitfalls</a></li>
<li><p>6.3. <a class="post-section-overview" href="#heading-62-avoiding-common-pitfalls">Testing Thunk Functions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-real-world-examples">Real-World Examples</a></p>
</li>
<li><p>7.1. <a class="post-section-overview" href="#heading-71-integration-with-react-applications">Integration with React Applications</a></p>
</li>
<li><p>7.2. <a class="post-section-overview" href="#heading-72-use-cases-in-large-scale-projects">Use Cases in Large-Scale Projects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-performance-considerations">Performance Considerations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-9-alternatives-to-redux-thunk">Alternatives to Redux-Thunk</a></p>
</li>
<li><p>9.1. <a class="post-section-overview" href="#heading-91-comparison-with-other-middleware">Comparison with Other Middleware</a></p>
</li>
<li>9.2. <a class="post-section-overview" href="#heading-92-when-to-choose-redux-thunk">When to Choose Redux-Thunk</a></li>
</ol>
<p><a class="post-section-overview" href="#heading-10-conclusion">10. Conclusion</a></p>
<h2 id="heading-1-introduction-to-redux-thunk">1. Introduction to Redux-Thunk</h2>
<p>Redux-Thunk is a middleware for Redux that allows you to write action creators that return a function instead of an action object. This function receives the store's <code>dispatch</code> method and <code>getState</code> function as arguments, allowing it to dispatch multiple actions, perform asynchronous operations, and access the current state if needed before dispatching an action.</p>
<h3 id="heading-11-understanding-middleware-in-redux">1.1. Understanding Middleware in Redux</h3>
<p>Before diving into Redux-Thunk, let's briefly discuss what middleware is in the context of Redux. </p>
<p>Middleware provides a way to interact with actions dispatched to the Redux store before they reach the reducer. It sits between the action dispatch and the reducer, allowing you to intercept, modify, or delay actions as needed. </p>
<p>It provides a way to extend Redux's functionality by intercepting and potentially modifying actions before they reach the reducers.</p>
<h3 id="heading-12-the-role-of-redux-thunk">1.2. The Role of Redux-Thunk</h3>
<p>The primary purpose of Redux-Thunk is to handle asynchronous actions in Redux. Asynchronous actions, such as fetching data from an API or performing asynchronous computations, are common in web applications. </p>
<p>Redux-Thunk enables you to dispatch actions asynchronously, making it easier to manage side effects in your Redux applications.</p>
<h2 id="heading-2-installation-and-setup">2. Installation and Setup</h2>
<p>Setting up Redux-Thunk in your Redux project is straightforward. First, you need to install the <code>redux-thunk</code> package using <code>npm</code> or <code>yarn</code>:</p>
<pre><code class="lang-bash">npm install redux-thunk
<span class="hljs-comment"># or</span>
yarn add redux-thunk
</code></pre>
<p>Once installed, you can integrate Redux-Thunk into your Redux store by applying it as middleware when creating the store:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>;

<span class="hljs-keyword">const</span> store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);
</code></pre>
<p>By applying Redux-Thunk middleware using <code>applyMiddleware</code>, you enable Redux to recognize and process thunk functions when they are dispatched.</p>
<h2 id="heading-3-working-with-redux-thunk">3. Working with Redux-Thunk</h2>
<p>Now that Redux-Thunk is set up in your project, let's explore how to work with it effectively.</p>
<h3 id="heading-31-writing-thunk-functions">3.1. Writing Thunk Functions</h3>
<p>Writing thunk functions in Redux involves defining asynchronous action creators that return a function instead of a plain action object. These functions have access to the <code>dispatch</code> and <code>getState</code> methods of the Redux store, allowing you to perform asynchronous operations and dispatch actions based on the results. </p>
<p>Here's how you can write thunk functions in Redux:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-comment">// Action types</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> FETCH_DATA_REQUEST = <span class="hljs-string">'FETCH_DATA_REQUEST'</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> FETCH_DATA_SUCCESS = <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> FETCH_DATA_FAILURE = <span class="hljs-string">'FETCH_DATA_FAILURE'</span>;

<span class="hljs-comment">// Action creators</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataRequest = <span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">type</span>: FETCH_DATA_REQUEST
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataSuccess = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: FETCH_DATA_SUCCESS,
  <span class="hljs-attr">payload</span>: data
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataFailure = <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: FETCH_DATA_FAILURE,
  <span class="hljs-attr">payload</span>: error
});

<span class="hljs-comment">// Thunk action creator</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch, getState) =&gt; {
    dispatch(fetchDataRequest());
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://api.example.com/data'</span>);
      dispatch(fetchDataSuccess(response.data));
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch(fetchDataFailure(error.message));
    }
  };
};
</code></pre>
<p>In this example:</p>
<ol>
<li>We defined action types for different stages of the data fetching process: request, success, and failure.</li>
<li>We defined action creators for each action type, which return plain action objects with the appropriate type and payload.</li>
<li>We defined a thunk action creator called <code>fetchData</code>, which returns a function instead of a plain action object. This function receives <code>dispatch</code> and <code>getState</code> as arguments, allowing us to dispatch actions and access the current Redux state.</li>
<li>Inside the thunk function, we dispatch the <code>FETCH_DATA_REQUEST</code> action to indicate that the data fetching process has started.</li>
<li>We used <code>axios</code> (you can use any other HTTP client) to make an asynchronous GET request to fetch data from an API endpoint.</li>
<li>If the request is successful, we dispatch the <code>FETCH_DATA_SUCCESS</code> action with the fetched data as the payload.</li>
<li>If the request fails, we dispatch the <code>FETCH_DATA_FAILURE</code> action with the error message as the payload.</li>
</ol>
<p>Thunk functions provide a flexible and powerful way to handle asynchronous actions in Redux, allowing you to encapsulate complex asynchronous logic and manage side effects effectively.</p>
<h3 id="heading-32-dispatching-thunk-actions">3.2. Dispatching Thunk Actions</h3>
<p>You can dispatch thunk actions just like regular actions using the <code>dispatch</code> method provided by the Redux store:</p>
<pre><code class="lang-javascript">store.dispatch(fetchUser());
</code></pre>
<p>When you dispatch a thunk action, Redux-Thunk intercepts it and invokes the thunk function with the <code>dispatch</code> method and <code>getState</code> function as arguments.</p>
<p>This allows the thunk function to perform asynchronous operations and dispatch additional actions if needed.</p>
<h2 id="heading-4-handling-asynchronous-operations">4. Handling Asynchronous Operations</h2>
<p>One of the main benefits of Redux-Thunk is its ability to handle asynchronous operations seamlessly. Let's explore some common scenarios where Redux-Thunk shines:</p>
<h3 id="heading-41-making-asynchronous-api-calls">4.1. Making Asynchronous API Calls</h3>
<p>Making asynchronous API calls in Redux thunks is a common use case for handling data fetching and updating in React applications. </p>
<p>Here's how you can make asynchronous API calls in Redux thunks:</p>
<h4 id="heading-a-import-necessary-dependencies">A. Import Necessary Dependencies</h4>
<p>First, make sure you have the necessary dependencies installed. You'll typically need Redux, Redux Thunk middleware, and a library for making HTTP requests, such as Axios or Fetch.</p>
<pre><code class="lang-bash">npm install redux redux-thunk axios
</code></pre>
<h4 id="heading-b-create-thunk-action-creators">B. Create Thunk Action Creators</h4>
<p>Define thunk action creators that will dispatch actions for handling API requests. Thunks are functions that return another function, allowing you to perform asynchronous operations before dispatching actions.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataRequest = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_REQUEST'</span> });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataSuccess = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataFailure = <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
    dispatch(fetchDataRequest());
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://api.example.com/data'</span>);
      dispatch(fetchDataSuccess(response.data));
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch(fetchDataFailure(error.message));
    }
  };
};
</code></pre>
<h4 id="heading-c-dispatch-thunk-actions">C. Dispatch Thunk Actions</h4>
<p>Dispatch the thunk action creator from your component when you need to fetch data. This will trigger the asynchronous API call and update the Redux store accordingly.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// SomeComponent.js</span>
<span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch, useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { fetchData } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>;

<span class="hljs-keyword">const</span> SomeComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> dispatch = useDispatch();
  <span class="hljs-keyword">const</span> { data, isLoading, error } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.someReducer);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    dispatch(fetchData());
  }, [dispatch]);

  <span class="hljs-keyword">if</span> (isLoading) {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  }

  <span class="hljs-keyword">if</span> (error) {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error: {error}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* Display fetched data */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SomeComponent;
</code></pre>
<h4 id="heading-d-update-reducer">D. Update Reducer</h4>
<p>Update the reducer to handle the dispatched actions and update the state accordingly.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// reducers.js</span>
<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
};

<span class="hljs-keyword">const</span> someReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_REQUEST'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">data</span>: action.payload, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_FAILURE'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">error</span>: action.payload, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> someReducer;
</code></pre>
<h4 id="heading-e-set-up-redux-store">E. Set Up Redux Store</h4>
<p>Finally, set up your Redux store with Redux Thunk middleware.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// store.js</span>
<span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>;

<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(thunk));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>Now your Redux application is set up to make asynchronous API calls using Redux thunks. Thunks provide a convenient way to handle asynchronous operations in Redux and integrate seamlessly with the Redux workflow.</p>
<h3 id="heading-42-managing-side-effects-with-thunks">4.2. Managing Side Effects with Thunks</h3>
<p>Managing side effects, such as asynchronous operations, in Redux applications can be effectively done using thunks. </p>
<p>Thunks allow you to encapsulate complex logic, including side effects, within action creators, providing a centralized and organized way to handle such operations. </p>
<p>Here's how you can manage side effects with thunks:</p>
<h4 id="heading-a-define-thunk-action-creators">A. Define Thunk Action Creators</h4>
<p>Create thunk action creators that encapsulate the asynchronous logic or side effects you want to manage. </p>
<p>Thunks are functions that return another function, giving you access to the <code>dispatch</code> function and the Redux store's <code>getState</code> method.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataRequest = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_REQUEST'</span> });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataSuccess = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataFailure = <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
    dispatch(fetchDataRequest());
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://api.example.com/data'</span>);
      dispatch(fetchDataSuccess(response.data));
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch(fetchDataFailure(error.message));
    }
  };
};
</code></pre>
<h4 id="heading-b-dispatch-thunk-actions">B. Dispatch Thunk Actions</h4>
<p>Dispatch the thunk action creator from your components when you need to trigger the side effect. This will execute the asynchronous logic encapsulated within the thunk.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// SomeComponent.js</span>
<span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch, useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { fetchData } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>;

<span class="hljs-keyword">const</span> SomeComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> dispatch = useDispatch();
  <span class="hljs-keyword">const</span> { data, isLoading, error } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.someReducer);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    dispatch(fetchData());
  }, [dispatch]);

  <span class="hljs-comment">// Render UI based on the fetched data, loading state, or error status</span>
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SomeComponent;
</code></pre>
<h4 id="heading-c-update-reducer">C. Update Reducer</h4>
<p>Update the reducer to handle the dispatched actions and update the Redux store state accordingly. This typically involves updating the state to reflect the loading state, success, or failure of the asynchronous operation.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// reducers.js</span>
<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>
};

<span class="hljs-keyword">const</span> someReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_REQUEST'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">data</span>: action.payload, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_DATA_FAILURE'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">error</span>: action.payload, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> someReducer;
</code></pre>
<h4 id="heading-d-set-up-redux-store-with-thunk-middleware">D. Set Up Redux Store with Thunk Middleware</h4>
<p>Ensure that you have set up your Redux store with Redux Thunk middleware to enable thunk action creators.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// store.js</span>
<span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>;

<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(thunk));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>With thunks, you can manage side effects such as data fetching, API calls, or any asynchronous operations in a structured and centralized manner within your Redux application. </p>
<p>Thunks promote separation of concerns and make it easier to test and maintain asynchronous logic within your Redux codebase.</p>
<h2 id="heading-5-advanced-techniques">5. Advanced Techniques</h2>
<p>Redux-Thunk offers several advanced techniques for handling complex scenarios. Let's explore some of them:</p>
<h3 id="heading-51-error-handling-in-thunks">5.1. Error Handling in Thunks</h3>
<p>Error handling in thunks is essential to ensure that your Redux application behaves predictably and gracefully handles errors that occur during asynchronous operations, such as API requests. </p>
<p>Here's how you can handle errors effectively in thunks:</p>
<h4 id="heading-a-catch-errors-in-thunks">A. Catch Errors in Thunks</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
    dispatch(fetchDataRequest());
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
      <span class="hljs-keyword">if</span> (!response.ok) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Failed to fetch data'</span>);
      }
      <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
      dispatch(fetchDataSuccess(data));
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch(fetchDataFailure(error.message));
    }
  };
};
</code></pre>
<p>In this example:</p>
<ul>
<li>We used a <code>try...catch</code> block to catch any errors that occur during the asynchronous operation (in this case, fetching data from an API).</li>
<li>If an error occurs, we dispatch an action to handle the error (<code>fetchDataFailure</code>), passing the error message as payload.</li>
</ul>
<h4 id="heading-b-handle-errors-appropriately">B. Handle Errors Appropriately</h4>
<ul>
<li>Dispatch specific error actions based on the type of error encountered.</li>
<li>Include meaningful error messages or error codes in error actions to provide context for debugging and user feedback.</li>
<li>Consider whether certain errors should trigger additional actions or side effects, such as logging errors or displaying error notifications.</li>
</ul>
<h4 id="heading-c-centralize-error-handling-logic">C. Centralize Error Handling Logic</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// sharedThunks.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handleApiError = <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">dispatch</span>) =&gt;</span> {
    dispatch(showErrorNotification(error.message));
    dispatch(logError(error));
  };
};
</code></pre>
<p>In this example:</p>
<ul>
<li>We defined a shared thunk (<code>handleApiError</code>) responsible for handling errors from API requests.</li>
<li>This thunk dispatches actions to display error notifications and log errors.</li>
<li>Centralizing error handling logic in shared thunks promotes consistency and reusability across different parts of your application.</li>
</ul>
<h4 id="heading-d-test-error-scenarios">D. Test Error Scenarios</h4>
<ul>
<li>Write unit tests to cover error handling scenarios in your thunks.</li>
<li>Mock API requests to simulate different error conditions, such as network errors or server errors.</li>
<li>Verify that the thunk dispatches the correct error actions and handles errors appropriately.</li>
</ul>
<h4 id="heading-e-consider-retry-strategies">E. Consider Retry Strategies</h4>
<ul>
<li>Implement retry strategies for handling transient errors, such as temporary network issues or rate-limiting errors.</li>
<li>Thunks can include retry logic to attempt the operation again after a delay or a certain number of retries.</li>
</ul>
<p>By effectively handling errors in thunks, you can improve the robustness and reliability of your Redux application, providing users with a better experience and simplifying debugging and maintenance efforts.</p>
<h3 id="heading-52-chaining-multiple-thunks">5.2. Chaining Multiple Thunks</h3>
<p>Thunks can be chained together to perform complex sequences of asynchronous operations. This is useful when you need to perform multiple asynchronous tasks sequentially:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fetchUserAndPosts = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch, getState) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Fetch user</span>
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_USER_REQUEST'</span> });
      <span class="hljs-keyword">const</span> userResponse = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/user'</span>);
      <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> userResponse.json();
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_USER_SUCCESS'</span>, <span class="hljs-attr">payload</span>: user });

      <span class="hljs-comment">// Fetch posts</span>
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_REQUEST'</span> });


 <span class="hljs-keyword">const</span> postsResponse = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/posts'</span>);
      <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> postsResponse.json();
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS_SUCCESS'</span>, <span class="hljs-attr">payload</span>: posts });
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_FAILURE'</span>, <span class="hljs-attr">error</span>: error.message });
    }
  };
};
</code></pre>
<p>By chaining multiple thunk functions together, you can orchestrate complex asynchronous workflows with ease.</p>
<h2 id="heading-6-best-practices">6. Best Practices</h2>
<p>While Redux-Thunk provides powerful capabilities for handling asynchronous actions, it's essential to follow best practices to ensure your code remains maintainable and efficient.</p>
<p>Here are some best practices to consider:</p>
<h3 id="heading-61-structuring-thunks-for-maintainability">6.1. Structuring Thunks for Maintainability</h3>
<p>Structuring thunks for maintainability is crucial to ensure that your Redux code remains organized, scalable, and easy to maintain as your application grows. </p>
<p>Here's a recommended approach for structuring thunks:</p>
<h3 id="heading-separate-concerns">Separate Concerns</h3>
<h4 id="heading-a-action-types-and-action-creators">a. Action Types and Action Creators</h4>
<ul>
<li>Define action types and action creators separately to promote reusability and maintainability.</li>
<li>Group related action types and creators in logical modules or files.</li>
</ul>
<h4 id="heading-b-thunk-functions">b. Thunk Functions</h4>
<ul>
<li>Define thunk functions separately from action creators to keep the concerns of asynchronous operations distinct from synchronous actions.</li>
</ul>
<h3 id="heading-modularize-thunks">Modularize Thunks</h3>
<h4 id="heading-a-module-level-thunks">a. Module-Level Thunks</h4>
<ul>
<li>Group related thunk functions within modules or feature slices of your application.</li>
<li>Each module can contain its own set of thunks responsible for handling asynchronous operations related to that module.</li>
</ul>
<h4 id="heading-b-reusable-thunks">b. Reusable Thunks</h4>
<ul>
<li>Extract reusable thunks into separate files or utility modules that can be shared across different parts of your application.</li>
<li>Common asynchronous operations, such as data fetching or authentication, can be encapsulated as reusable thunks.</li>
</ul>
<h3 id="heading-encapsulate-complex-logic">Encapsulate Complex Logic</h3>
<h4 id="heading-a-action-composition">a. Action Composition</h4>
<ul>
<li>Encapsulate complex logic related to action composition within thunks.</li>
<li>Thunks can orchestrate multiple synchronous actions to perform a higher-level operation.</li>
</ul>
<h4 id="heading-b-error-handling">b. Error Handling:</h4>
<ul>
<li>Centralize error handling logic within thunks to ensure consistent error reporting and recovery strategies.</li>
<li>Thunks can catch and handle errors from asynchronous operations before dispatching appropriate error actions.</li>
</ul>
<h3 id="heading-use-asyncawait-for-readability">Use Async/Await for Readability</h3>
<h4 id="heading-a-asyncawait-syntax">a. Async/Await Syntax</h4>
<ul>
<li>Use async/await syntax within thunks for cleaner and more readable asynchronous code.</li>
<li>Async functions make it easier to manage asynchronous control flow when compared to using raw Promises.</li>
</ul>
<h3 id="heading-example-structure">Example Structure</h3>
<p>Here's an example of how you can structure thunks for maintainability:</p>
<pre><code class="lang-plaintext">src/
├── actions/
│   ├── actionTypes.js
│   ├── feature1Actions.js
│   ├── feature2Actions.js
│   └── ...
├── thunks/
│   ├── feature1Thunks.js
│   ├── feature2Thunks.js
│   ├── sharedThunks.js
│   └── index.js
├── reducers/
│   ├── feature1Reducer.js
│   ├── feature2Reducer.js
│   └── ...
└── store.js
</code></pre>
<p>In this structure:</p>
<ul>
<li><code>feature1Thunks.js</code> and <code>feature2Thunks.js</code> contain thunks specific to different features/modules of your application.</li>
<li><code>sharedThunks.js</code> contains reusable thunks shared across multiple features.</li>
<li><code>index.js</code> exports all thunks to be imported into the Redux store setup.</li>
<li>Action types and action creators are defined in separate files within the <code>actions</code> directory.</li>
</ul>
<p>By structuring thunks in a modular and organized manner, you can improve the maintainability of your Redux codebase. </p>
<p>Separating concerns, encapsulating complex logic, and promoting reusability will make it easier to manage and extend your application's asynchronous behavior over time.</p>
<h3 id="heading-62-avoiding-common-pitfalls">6.2. Avoiding Common Pitfalls</h3>
<p>Avoiding common pitfalls when working with Redux-Thunk can help maintain a smoother development process and ensure the reliability of your Redux applications. </p>
<p>Here are some common pitfalls to watch out for and how to avoid them:</p>
<h4 id="heading-overusing-thunks-for-synchronous-actions">Overusing Thunks for Synchronous Actions</h4>
<ul>
<li>Thunks are primarily meant for handling asynchronous actions. Overusing them for synchronous actions can lead to unnecessary complexity in your code.</li>
<li><strong>Solution</strong>: Reserve thunks for asynchronous actions like data fetching or API calls. For synchronous actions, define regular action creators that directly return action objects.</li>
</ul>
<h4 id="heading-excessive-logic-in-thunks">Excessive Logic in Thunks</h4>
<ul>
<li>Putting too much logic inside thunks can make them hard to understand, test, and maintain.</li>
<li><strong>Solution</strong>: Keep thunks focused on dispatching actions and handling asynchronous operations. Extract complex logic into separate functions or utilities that can be tested independently.</li>
</ul>
<h4 id="heading-lack-of-error-handling">Lack of Error Handling</h4>
<ul>
<li>Failing to handle errors properly in thunks can result in unexpected behavior or application crashes.</li>
<li><strong>Solution</strong>: Ensure that your thunks handle errors gracefully by catching exceptions and dispatching appropriate error actions. This includes handling errors from asynchronous operations like API requests.</li>
</ul>
<h4 id="heading-inefficient-data-fetching">Inefficient Data Fetching</h4>
<ul>
<li>Inefficient data fetching practices, such as fetching the same data repeatedly or fetching unnecessary data, can impact performance.</li>
<li><strong>Solution</strong>: Implement caching mechanisms to store fetched data locally and avoid redundant API requests. Use memoization techniques or selectors to optimize data fetching and avoid unnecessary re-rendering.</li>
</ul>
<h4 id="heading-poor-testing-practices">Poor Testing Practices</h4>
<ul>
<li>Inadequate testing of thunks can result in undetected bugs and regressions.</li>
<li><strong>Solution</strong>: Write comprehensive unit tests for your thunks to cover different scenarios, including successful and failed asynchronous operations. Mock external dependencies like API requests to isolate the behavior of thunks.</li>
</ul>
<h4 id="heading-uncontrolled-side-effects">Uncontrolled Side Effects</h4>
<ul>
<li>Thunks that trigger unintended side effects or have unpredictable behavior can lead to bugs and unexpected application states.</li>
<li><strong>Solution</strong>: Be mindful of the side effects introduced by your thunks, such as modifying global state or interacting with external systems. Keep side effects under control and clearly document the behavior of your thunks.</li>
</ul>
<h4 id="heading-complex-middleware-composition">Complex Middleware Composition</h4>
<ul>
<li>Adding multiple middleware layers, such as logging or analytics, without proper organization and coordination can make the middleware pipeline hard to manage.</li>
<li><strong>Solution</strong>: Keep the middleware composition simple and well-organized. Use middleware libraries like Redux DevTools Extension to debug and monitor middleware behavior during development.</li>
</ul>
<p>By avoiding these common pitfalls and following best practices when working with Redux-Thunk, you can improve the reliability, performance, and maintainability of your Redux applications.</p>
<h3 id="heading-63-testing-thunk-functions">6.3. Testing Thunk Functions</h3>
<p>Testing thunk functions in Redux applications is crucial to ensure that asynchronous actions behave as expected. </p>
<p>When testing thunk functions, you want to verify that the correct actions are dispatched under various conditions, such as successful API requests, failed requests, or edge cases. </p>
<p>Here's how you can test thunk functions using popular testing frameworks like Jest and testing utilities like Redux Mock Store:</p>
<h3 id="heading-example-test-setup">Example Test Setup</h3>
<p>Let's assume we have a thunk function called <code>fetchData</code> that fetches data from an API and dispatches corresponding actions based on the result:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataRequest = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_REQUEST'</span> });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataSuccess = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchDataFailure = <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error });

<span class="hljs-comment">// thunks.js</span>
<span class="hljs-keyword">import</span> { fetchDataRequest, fetchDataSuccess, fetchDataFailure } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
    dispatch(fetchDataRequest());
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
      <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
      dispatch(fetchDataSuccess(data));
    } <span class="hljs-keyword">catch</span> (error) {
      dispatch(fetchDataFailure(error.message));
    }
  };
};
</code></pre>
<h3 id="heading-writing-tests">Writing Tests</h3>
<p>Here's how you can write tests for the <code>fetchData</code> thunk function:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// thunks.test.js</span>
<span class="hljs-keyword">import</span> configureMockStore <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-mock-store'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> fetchMock <span class="hljs-keyword">from</span> <span class="hljs-string">'jest-fetch-mock'</span>;
<span class="hljs-keyword">import</span> { fetchData } <span class="hljs-keyword">from</span> <span class="hljs-string">'./thunks'</span>;
<span class="hljs-keyword">import</span> { fetchDataRequest, fetchDataSuccess, fetchDataFailure } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>;

<span class="hljs-keyword">const</span> middlewares = [thunk];
<span class="hljs-keyword">const</span> mockStore = configureMockStore(middlewares);

fetchMock.enableMocks();

describe(<span class="hljs-string">'fetchData thunk'</span>, <span class="hljs-function">() =&gt;</span> {
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    fetchMock.resetMocks();
  });

  it(<span class="hljs-string">'dispatches fetchDataSuccess action after successful API request'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> mockData = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Example Data'</span> };
    fetchMock.mockResponse(<span class="hljs-built_in">JSON</span>.stringify(mockData));
    <span class="hljs-keyword">const</span> expectedActions = [
      fetchDataRequest(),
      fetchDataSuccess(mockData)
    ];
    <span class="hljs-keyword">const</span> store = mockStore();

    <span class="hljs-keyword">await</span> store.dispatch(fetchData());
    expect(store.getActions()).toEqual(expectedActions);
  });

  it(<span class="hljs-string">'dispatches fetchDataFailure action after failed API request'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> errorMessage = <span class="hljs-string">'Failed to fetch data'</span>;
    fetchMock.mockReject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(errorMessage));
    <span class="hljs-keyword">const</span> expectedActions = [
      fetchDataRequest(),
      fetchDataFailure(errorMessage)
    ];
    <span class="hljs-keyword">const</span> store = mockStore();

    <span class="hljs-keyword">await</span> store.dispatch(fetchData());
    expect(store.getActions()).toEqual(expectedActions);
  });
});
</code></pre>
<p>Here's what happens in the code above:</p>
<h4 id="heading-mocking-fetch-api">Mocking Fetch API:</h4>
<ul>
<li>We used Jest's <code>fetchMock</code> to mock the <code>fetch</code> function, allowing us to control its behavior during testing.</li>
</ul>
<h4 id="heading-configuring-redux-mock-store">Configuring Redux Mock Store:</h4>
<ul>
<li>We configured a mock Redux store using <code>redux-mock-store</code>, enabling us to simulate Redux store behavior in our tests.</li>
</ul>
<h4 id="heading-dispatching-thunk-function">Dispatching Thunk Function:</h4>
<ul>
<li>We dispatched the <code>fetchData</code> thunk function using the mock store and then await its completion.</li>
</ul>
<h4 id="heading-expectations">Expectations:</h4>
<ul>
<li>We assert that the expected actions are dispatched based on different scenarios (successful or failed API requests).</li>
</ul>
<h4 id="heading-resetting-mocks">Resetting Mocks:</h4>
<ul>
<li>We reset the mocks before each test to ensure that they start in a clean state.</li>
</ul>
<p>By writing tests for thunk functions in this manner, you can verify their behavior under various conditions, ensuring the reliability and correctness of your Redux application's asynchronous actions.</p>
<h2 id="heading-7-real-world-examples">7. Real-World Examples</h2>
<p>To demonstrate the practical use of Redux-Thunk, let's look at some real-world examples of how it can be used in a Redux application.</p>
<h3 id="heading-71-integration-with-react-applications">7.1. Integration with React Applications</h3>
<p>Redux-Thunk integrates seamlessly with React applications, allowing you to manage asynchronous data fetching, state updates, and side effects efficiently. </p>
<p>Here's a simple example of using Redux-Thunk with React:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Component.js</span>
<span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch, useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { fetchUser } <span class="hljs-keyword">from</span> <span class="hljs-string">'./redux/userThunks'</span>;

<span class="hljs-keyword">const</span> Component = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> dispatch = useDispatch();
  <span class="hljs-keyword">const</span> user = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.user);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    dispatch(fetchUser());
  }, [dispatch]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {user ? <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> : <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Component;
</code></pre>
<h3 id="heading-72-use-cases-in-large-scale-projects">7.2. Use Cases in Large-Scale Projects</h3>
<p>In large-scale React projects, Redux-Thunk can be a valuable tool for managing asynchronous actions and handling complex logic. </p>
<p>Here are some common use cases for Redux-Thunk in large-scale projects:</p>
<h4 id="heading-data-fetching">Data Fetching</h4>
<ul>
<li>Large-scale applications often need to fetch data from multiple APIs or endpoints. Redux-Thunk allows you to encapsulate these asynchronous operations in action creators.</li>
<li>You can handle scenarios like fetching initial data when a component mounts, paginating through large datasets, or refreshing data periodically.</li>
</ul>
<h4 id="heading-authentication">Authentication</h4>
<ul>
<li>Implementing authentication flows, such as logging in, logging out, or refreshing tokens, often involves asynchronous operations like making API requests and updating the user's authentication state.</li>
<li>Redux-Thunk can manage these operations, dispatching actions to update the authentication state based on the API responses and handling any errors that occur during the process.</li>
</ul>
<h4 id="heading-form-submission">Form Submission</h4>
<ul>
<li>Large-scale forms with complex validation requirements and submission processes may require asynchronous actions to handle form submissions.</li>
<li>Redux-Thunk can dispatch actions to submit form data, handle server responses (success or error), and update the application state accordingly.</li>
</ul>
<h4 id="heading-optimistic-updates">Optimistic Updates</h4>
<ul>
<li>In applications where user interactions trigger asynchronous actions with optimistic UI updates, Redux-Thunk can help manage the flow of actions.</li>
<li>You can dispatch optimistic actions to update the UI immediately and then dispatch additional actions based on the success or failure of the asynchronous operation.</li>
</ul>
<h4 id="heading-websocket-integration">WebSocket Integration</h4>
<ul>
<li>Large-scale applications often use WebSocket connections for real-time communication with servers.</li>
<li>Redux-Thunk can be used to manage WebSocket connections and dispatch actions in response to incoming messages or events, such as updating UI components or triggering additional actions.</li>
</ul>
<h4 id="heading-complex-business-logic">Complex Business Logic</h4>
<ul>
<li>As applications grow in complexity, they may require more sophisticated business logic to handle various scenarios and edge cases.</li>
<li>Redux-Thunk allows you to encapsulate complex logic within action creators, making it easier to manage and test.</li>
</ul>
<h4 id="heading-middleware-composition">Middleware Composition</h4>
<ul>
<li>In large-scale projects, you may have multiple middleware layers in your Redux setup for tasks like logging, error handling, or analytics.</li>
<li>Redux-Thunk can be seamlessly integrated into the middleware pipeline, allowing you to compose multiple middleware functions to handle different aspects of your application's behavior.</li>
</ul>
<p>By leveraging Redux-Thunk in these use cases, you can effectively manage asynchronous actions, handle complex application logic, and maintain a scalable and maintainable codebase in large-scale React projects.</p>
<h2 id="heading-8-performance-considerations">8. Performance Considerations</h2>
<p>While Redux-Thunk provides powerful capabilities for handling asynchronous actions, it's essential to consider its impact on the performance of your application. </p>
<p>Here are some performance considerations to keep in mind:</p>
<h4 id="heading-asynchronous-operations">Asynchronous Operations</h4>
<p>Redux-Thunk enables handling asynchronous operations, such as making API requests or performing computations that take time to complete. </p>
<p>These operations can introduce latency into your application, impacting overall performance.</p>
<h4 id="heading-blocking-the-event-loop">Blocking the Event Loop</h4>
<p>Long-running synchronous tasks within thunks can potentially block the JavaScript event loop, leading to unresponsive user interfaces. </p>
<p>Avoid blocking the event loop by offloading heavy computations to worker threads or breaking them into smaller asynchronous tasks.</p>
<h4 id="heading-middleware-overhead">Middleware Overhead</h4>
<p>Adding middleware to the Redux middleware pipeline incurs a slight performance overhead, as each middleware function needs to process dispatched actions sequentially. </p>
<p>While this overhead is generally minimal, it's essential to keep middleware composition efficient.</p>
<h4 id="heading-thunk-composition">Thunk Composition</h4>
<p>The composition of multiple thunks can impact performance, especially if thunks trigger additional asynchronous operations sequentially. </p>
<p>Carefully consider thunk composition to minimize unnecessary delays and optimize performance.</p>
<h4 id="heading-redux-devtools-integration">Redux DevTools Integration</h4>
<p>Enabling Redux DevTools for debugging purposes can impact performance, especially when recording or replaying actions. </p>
<p>Use Redux DevTools judiciously, especially in production environments, to minimize performance overhead.</p>
<h4 id="heading-memoization-and-caching">Memoization and Caching</h4>
<p>Implement memoization techniques or caching for fetched data to reduce redundant computations and API requests. </p>
<p>Memoization ensures that expensive computations are performed only when necessary, improving application responsiveness.</p>
<h4 id="heading-code-splitting-and-dynamic-imports">Code Splitting and Dynamic Imports</h4>
<p>Consider code-splitting your Redux-related code and dynamically importing thunks or reducers only when needed. This approach can reduce the initial bundle size of your application and improve load times, especially for large-scale applications.</p>
<h4 id="heading-testing-and-profiling">Testing and Profiling</h4>
<p>Regularly test and profile your application to identify performance bottlenecks and areas for optimization. Use performance profiling tools to measure the impact of Redux-Thunk on application responsiveness and identify opportunities for improvement.</p>
<p>By considering these performance considerations and following best practices, you can ensure that your Redux-Thunk-based application remains responsive and efficient, providing a smooth user experience. Balancing the power of Redux-Thunk with performance optimizations is essential for building high-performing Redux applications.</p>
<h2 id="heading-9-alternatives-to-redux-thunk">9. Alternatives to Redux-Thunk</h2>
<p>While Redux-Thunk is a popular choice for handling asynchronous actions in Redux, there are alternative middleware solutions available that offer similar or additional capabilities. </p>
<p>Some popular alternatives to Redux-Thunk include Redux-Saga, Redux-Observable.</p>
<h3 id="heading-91-comparison-with-other-middleware">9.1. Comparison with Other Middleware</h3>
<p>Each middleware solution has its own strengths and weaknesses, depending on the specific requirements of your application. </p>
<p>Here's a brief comparison of Redux-Thunk with other middleware solutions:</p>
<h4 id="heading-redux-saga">Redux-Saga</h4>
<ul>
<li>Redux-Saga is a library for managing side effects in Redux applications. It uses ES6 Generators to make asynchronous code easier to read, write, and test.</li>
<li>Sagas are defined as separate functions that listen for specific Redux actions and can then perform asynchronous operations in a more declarative and testable way.</li>
<li>Redux-Saga is great for handling complex asynchronous logic, such as race conditions, cancellations, and retries.</li>
</ul>
<p>Here's an example of a Redux-Saga:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">yield</span> call(api.fetchData);
    <span class="hljs-keyword">yield</span> put({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">yield</span> put({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error });
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watchFetchData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> takeEvery(<span class="hljs-string">'FETCH_DATA_REQUEST'</span>, fetchData);
}
</code></pre>
<h4 id="heading-redux-thunk-extra">Redux-Thunk-Extra</h4>
<ul>
<li>Redux-Thunk-Extra is an enhanced version of Redux-Thunk with additional features like promise support and action creators for starting, succeeding, and failing async operations.</li>
<li>It provides a simpler API when compared to Redux-Saga and can be a good choice if you prefer the familiar thunk-style syntax but need more features.</li>
</ul>
<p>Here's an example of using Redux-Thunk-Extra with promises:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">dispatch</span>) =&gt;</span> {
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_START'</span> });

    api.fetchData()
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data }))
      .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error }));
  };
};
</code></pre>
<h4 id="heading-redux-observable">Redux-Observable</h4>
<ul>
<li>Redux-Observable is a middleware for Redux based on RxJS, a powerful library for reactive programming.</li>
<li>It allows you to express complex asynchronous workflows using observable streams, making it suitable for handling events over time, such as user inputs or WebSocket connections.</li>
<li>Redux-Observable is a good choice for applications with a heavy focus on reactive programming or where you need fine-grained control over asynchronous behavior.</li>
</ul>
<p>Here's an example of using Redux-Observable:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fetchDataEpic = action$ =&gt; action$.pipe(
  ofType(<span class="hljs-string">'FETCH_DATA_REQUEST'</span>),
  mergeMap(<span class="hljs-function">() =&gt;</span>
    ajax.getJSON(<span class="hljs-string">'https://api.example.com/data'</span>).pipe(
      map(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> ({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: response })),
      catchError(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-keyword">of</span>({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error }))
    )
  )
);
</code></pre>
<h4 id="heading-fetch-api-with-asyncawait">Fetch API with Async/Await</h4>
<ul>
<li>If your asynchronous operations are relatively simple and you prefer to keep your dependencies minimal, you can use the Fetch API combined with async/await syntax directly in your action creators without any middleware.</li>
<li>This approach works well for simple data fetching scenarios but may become unwieldy for more complex async logic.</li>
</ul>
<p>Each of these alternatives has its own strengths and use cases, so choose the one that best fits your project requirements and coding preferences.</p>
<h3 id="heading-92-when-to-choose-redux-thunk">9.2. When to Choose Redux-Thunk</h3>
<p>Redux-Thunk is an excellent choice for handling simple to moderately complex asynchronous actions in Redux applications. It's lightweight, easy to understand, and integrates seamlessly with existing Redux codebases. </p>
<p>Consider using Redux-Thunk for:</p>
<h4 id="heading-asynchronous-operations-1">Asynchronous Operations</h4>
<ul>
<li>Use Redux-Thunk when you need to perform asynchronous operations like fetching data from an API, handling timers, or any operation that doesn't immediately return a value.</li>
</ul>
<p>Here's an example of how Redux-Thunk handles an asynchronous action, like fetching data:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Action creator with Redux-Thunk</span>
<span class="hljs-keyword">const</span> fetchData = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">dispatch</span>) =&gt;</span> {
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_REQUEST'</span> });

    fetch(<span class="hljs-string">'https://api.example.com/data'</span>)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_SUCCESS'</span>, <span class="hljs-attr">payload</span>: data }))
      .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_DATA_FAILURE'</span>, <span class="hljs-attr">payload</span>: error }));
  };
};
</code></pre>
<h4 id="heading-middleware-functionality">Middleware Functionality</h4>
<ul>
<li>Redux-Thunk is a middleware, meaning it sits between an action being dispatched and the moment it reaches the reducer. This allows for additional functionality like logging, modifying actions, or handling side effects.</li>
<li>If you need to perform actions before or after an action is dispatched, Redux-Thunk is a good choice.</li>
</ul>
<h4 id="heading-simple-setup">Simple Setup</h4>
<ul>
<li>Redux-Thunk integrates seamlessly with Redux, requiring minimal setup. It's easy to add to an existing Redux project.</li>
</ul>
<p>Here's how you can add Redux-Thunk to your Redux store:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-thunk'</span>;
<span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers'</span>;

<span class="hljs-keyword">const</span> store = createStore(rootReducer, applyMiddleware(thunk));
</code></pre>
<h4 id="heading-handling-complex-logic">Handling Complex Logic</h4>
<ul>
<li>If your application involves complex asynchronous logic, such as multiple API calls or conditional dispatching, Redux-Thunk provides a straightforward way to manage such complexity.</li>
<li>You can encapsulate complex logic within thunk action creators, keeping your components clean and focused on presentation.</li>
</ul>
<h4 id="heading-community-support-and-resources">Community Support and Resources</h4>
<ul>
<li>Redux-Thunk is a widely used middleware for Redux, which means there are plenty of resources, tutorials, and community support available.</li>
<li>If you're new to Redux or asynchronous data fetching in Redux, choosing Redux-Thunk can provide you with a wealth of learning materials and examples.</li>
</ul>
<p>Choose Redux-Thunk when you need to handle asynchronous operations in your Redux application, want to keep your setup simple, require middleware functionality, need to manage complex logic, or benefit from community support and resources. </p>
<h2 id="heading-10-conclusion">10. Conclusion</h2>
<p>Redux-Thunk is a powerful middleware for handling asynchronous actions in Redux applications. By allowing you to write thunk functions that encapsulate asynchronous logic, Redux-Thunk simplifies the process of managing side effects and coordinating complex workflows. </p>
<p>Whether you're fetching data from an API, performing background computations, or synchronizing state across different parts of your application, Redux-Thunk provides a flexible and intuitive solution for managing asynchronous actions in Redux.</p>
<p>In this comprehensive guide, we've covered everything you need to know about Redux-Thunk, from installation and setup to advanced techniques and best practices. </p>
<p>By following the principles outlined in this guide and applying them to your Redux projects, you'll be well-equipped to handle asynchronous actions effectively and build robust, maintainable Redux applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ State Management in React – When and Where to use State ]]>
                </title>
                <description>
                    <![CDATA[ State management is a crucial concept in React, which is one of the most popular JavaScript libraries in the world for building dynamic user interfaces.  Due to its importance in handling data, it is essential know how to manage state, when you need ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-state-management/</link>
                <guid isPermaLink="false">66ba2929c346e93df556afe6</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 05 Feb 2024 21:06:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/rahul-mishra-XXMA-8fBB-g-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is a crucial concept in React, which is one of the most popular JavaScript libraries in the world for building dynamic user interfaces. </p>
<p>Due to its importance in handling data, it is essential know how to manage state, when you need it, and where it can be placed in your applications’ components. </p>
<p>This article dives into the world of React state management, providing a comprehensive guide to help you manage state efficiently. This article is for beginners and intermediate-level of React developers that want to understand how states work.</p>
<h2 id="heading-what-is-state">What is State?</h2>
<p>State can be defined as an object that houses data that changes over time in an application. In other words, state is a dynamic data storage that provides a mechanism for components to manage, keep track of changing data, and trigger re-rendering when it is updated. </p>
<p>Due to modularization in React, state serves as a container that encapsulates relevant data, logic, and behavior within a component. </p>
<p>Now that you know what state means, you can visualize an application even before building it and have an idea of what data would be stored in different states. This brings us to a point I like to call: ‘Thinking In React’. </p>
<p>This coined terminology can be described as the mental picture a React developer has on how to go about building an application in the ‘React way’. Applying knowledge on keeping components pure, passing props from parent to child components, one-way data flow, lifting states up, and many other integral aspects of React.</p>
<h2 id="heading-when-to-use-state">When to Use State</h2>
<p>When building an application, data plays an integral role in what is been displayed or stored. The same applies to building web applications in React, where components display or operate on data — which can be user input, data fetched from APIs, or any other dynamic content. When there is a need to get data that has to be updated inside of a component, we use state.</p>
<p>To understand this better, let’s look at an example of a simple Todo List app that primarily accepts inputted items that would eventually be added to a displayed list. </p>
<p>The item's names will be defined via a text input before being dynamically added to an array of items. </p>
<p>So, we've identified two aspects involving data that would change when triggered. Any update to the data will cause the component to re-render. Those two aspects need the <code>useState</code> hook to update their data and perform the respective logic attached to them.</p>
<pre><code class="lang-react">const [name, setName] = useState(" ")
const [items, setItems] = useState([]);
</code></pre>
<p>Above, is the representation of <code>useState</code> hook functions that allow components to have state variables. As regards to our example of the Todo List app, we initialized our <code>useState</code> function with an empty string (“ ”) for the item names and an empty array (<code>[ ]</code>) for the items. </p>
<p>The <code>useState</code> functions consist of a destructuring assignment that extracts values from an array or properties from an object. In this instance, we are extracting two values returned by the <code>useState</code> functions. </p>
<p><code>name</code> and <code>items</code> hold the current value of the state variable. While <code>setName</code> and <code>setItems</code> are the functions used to update the value of the state variables. </p>
<p>We can add the <code>Header</code>, <code>Nav</code>, <code>ListArea</code> and <code>Footer</code> components to the <code>App</code> component's JSX. Our root component should look like this:</p>
<pre><code class="lang-react">import { useState } from "react";

export default function App() {
      const [items, setItems] = useState([]);
    const [name, setName] = useState(" ")
  return (
    &lt;div&gt;
      &lt;Header /&gt;
      &lt;Nav /&gt;
      &lt;ListArea /&gt;
      &lt;Footer /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>The individual components with their JSX's should look like this:</p>
<pre><code class="lang-react">function Header() {
  return &lt;h2&gt;ToDo List&lt;/h2&gt;;
}

function Nav() {
  return (
    &lt;&gt;
      &lt;input type="text"/&gt;
      &lt;button&gt;Add&lt;/button&gt;
    &lt;/&gt;
  );
}

function ListArea() {
  return (
    &lt;&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/&gt;
  );
}

function Footer() {
  return (
    &lt;&gt;
      &lt;p&gt;You have items in your cart&lt;/p&gt;
    &lt;/&gt;
  );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>How our component's JSXs looks in the browser</em></p>
<p>This is a simple representation of our Todo List. Next, we'll add some logic and make the states come to life. For now, the states reside in the <code>App</code> component.</p>
<h2 id="heading-where-to-use-state">Where to Use State</h2>
<p>When using state, it is important to note that there are two types of states in React development:</p>
<h3 id="heading-global-state">Global State</h3>
<p>These are states that are accessible to every component in the application. It is always declared and located in the root component of your app before the JSX is returned.</p>
<p>A state can be considered as a global state if it is a piece of data that is accessible among multiple components thereby, aiding communication between components in the application.</p>
<h3 id="heading-local-state">Local State</h3>
<p>Local states refers to the internal data maintained by a component. Local states are located within the parent components in an application. They are only needed and can be accessed in the component. </p>
<p>Using local state, components can independently change and handle their data which leads to partitioning within the application.</p>
<p>Looking at our declared states in the Todo List app, we can say that <code>name</code> is a local state and <code>items</code> is a global state.</p>
<p>The reasons are:</p>
<ul>
<li>Two or more components will need access to the <code>items</code> state.</li>
<li>The <code>name</code> state is only needed to input item names into the <code>items</code> list.</li>
</ul>
<p>Here is the structure of our Todo List application with the states positioned according to where they are needed and logic of adding item names to the items list:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//Global state</span>
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

<span class="hljs-comment">//handler function that takes item as a parameter</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleAddItems</span>(<span class="hljs-params">item</span>) </span>{

  <span class="hljs-comment">//setter function that returns a new array with elements from current state with a new item  </span>
    setItems(<span class="hljs-function">(<span class="hljs-params">items</span>) =&gt;</span> [...items, item]);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Nav</span> <span class="hljs-attr">handleAddItems</span>=<span class="hljs-string">{handleAddItems}</span> /&gt;</span> //passing handleAddItems as props
      <span class="hljs-tag">&lt;<span class="hljs-name">ListArea</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{items}</span> /&gt;</span> //passing items as props
      <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{items}</span> /&gt;</span>    //passing items as props
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>ToDo List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Nav</span>(<span class="hljs-params">{ handleAddItems }</span>) </span>{
  <span class="hljs-comment">//Local state function</span>
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-comment">//create a handler function that is triggered by Add button</span>
  <span class="hljs-keyword">const</span> handleAddButtonClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//creating a newItem object with name and id properties</span>
    <span class="hljs-keyword">const</span> newItem = { name, <span class="hljs-attr">id</span>: <span class="hljs-built_in">Date</span>.now() };

    <span class="hljs-comment">//passing the newItem object into the handler function as an argument</span>
    handleAddItems(newItem);
    <span class="hljs-comment">// Reset the input field after adding the item</span>
    setName(<span class="hljs-string">""</span>);
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setName(e.target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleAddButtonClick}</span>&gt;</span>Add<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-comment">//ListArea component recieving items as props from global state</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ListArea</span>(<span class="hljs-params">{ items }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      //mapping over items array to get individual item as list items
        {items.map((item) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-comment">//Footer component recieving items as props from global state</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Footer</span>(<span class="hljs-params">{ items }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {items.length !== 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You have {items.length} items in your cart<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You can start adding items to your list<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>The <code>Footer</code> and <code>ListArea</code> components now have access to the items passed down through props. </p>
<p>The act of positioning a state in the root component so it can be accessed globally in a React application is known as "Lifting State Up"- which was what we did with the <code>items</code> state.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Todo List after items have been added to the list</em></p>
<p>Here's a representation of the whole process:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we explored state management in React, when you need them, and where to place state in our applications’ components. </p>
<p>We also broke down how to ‘think in React’, to make our React components interact with each other and give the required output. </p>
<p>React is an interesting user interface library, but can get confusing sometimes if you don’t know the basics. You can now use the knowledge gained in this article to code your projects.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Manage State in React Apps with APIs – Redux, Context API, and Recoil Examples ]]>
                </title>
                <description>
                    <![CDATA[ State management is a crucial aspect of building robust and scalable React applications, especially when dealing with APIs.  As your application grows in complexity, efficiently managing the state becomes essential for a smooth user experience.  In t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/manage-state-in-react-apps-with-apis/</link>
                <guid isPermaLink="false">66c4c40c8e05d0e4345147d0</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jan 2024 00:18:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is a crucial aspect of building robust and scalable React applications, especially when dealing with APIs. </p>
<p>As your application grows in complexity, efficiently managing the state becomes essential for a smooth user experience. </p>
<p>In the React ecosystem, there are several options for state management, each with its own strengths and weaknesses. In this article, we'll explore three popular state management solutions: Redux, Context API, and Recoil, and see how they handle state in the context of API interactions.</p>
<h2 id="heading-introduction-to-state-management">Introduction to State Management</h2>
<p>Before diving into the specifics of each state management solution, let's briefly understand what state management is and why it's important in React development.</p>
<h3 id="heading-what-is-state">What is State?</h3>
<p>In React, state represents the data that can change over time. It is what allows a component to keep track of information and re-render when that information changes. For example, a button component might have a state to track whether it has been clicked or not.</p>
<h3 id="heading-why-manage-state">Why Manage State?</h3>
<p>As React applications grow, managing state becomes more complex. Passing state between components through props can become cumbersome, and it might lead to "prop drilling," where you pass data through many layers of components. </p>
<p>State management libraries aim to solve this problem by providing a centralized way to manage and share state across components.</p>
<h2 id="heading-redux-battle-tested-state-management">Redux: Battle-Tested State Management</h2>
<p>Redux has been a popular state management library in the React ecosystem for many years. It is based on the principles of a unidirectional data flow and provides a single source of truth for the entire application state.</p>
<h3 id="heading-how-to-install-redux">How to Install Redux</h3>
<p>To use Redux in a React project, you need to install both the <code>redux</code> and <code>react-redux</code> packages. Open your terminal and run the following command:</p>
<pre><code class="lang-bash">npm install redux react-redux
</code></pre>
<p>This command installs the core Redux library (<code>redux</code>) and the official React bindings for Redux (<code>react-redux</code>).</p>
<h3 id="heading-how-to-set-up-redux">How to Set Up Redux</h3>
<p>Redux follows a unidirectional data flow, which means that data in an application flows in a single direction, making it easier to understand and manage. Setting up Redux involves creating a store to hold the application state, defining actions to describe state changes, and implementing reducers to handle those changes.</p>
<h4 id="heading-creating-a-redux-store">Creating a Redux Store</h4>
<p>A Redux store is a container that holds the entire state tree of your application. You create a store by passing a reducer function to the <code>createStore</code> function from the <code>redux</code> package.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// store.js</span>
<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-comment">// Reducer</span>
<span class="hljs-keyword">const</span> counterReducer = <span class="hljs-function">(<span class="hljs-params">state = { count: <span class="hljs-number">0</span> }, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-comment">// Store</span>
<span class="hljs-keyword">const</span> store = createStore(counterReducer);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>In the code above:</p>
<ul>
<li>We create a reducer function (<code>counterReducer</code>) that takes the current state and an action, then returns the new state based on the action type.</li>
<li>The store is created using <code>createStore</code> and initialized with our reducer.</li>
</ul>
<h4 id="heading-how-to-interact-with-the-redux-store-in-a-component">How to Interact with the Redux Store in a Component</h4>
<p>To interact with the Redux store in a React component, we use the <code>useSelector</code> and <code>useDispatch</code> hooks provided by <code>react-redux</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// CounterComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-keyword">const</span> CounterComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Select the count from the store</span>
  <span class="hljs-keyword">const</span> count = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.count);

  <span class="hljs-comment">// Get the dispatch function</span>
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'INCREMENT' })}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'DECREMENT' })}&gt;Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterComponent;
</code></pre>
<p>In the <code>CounterComponent</code>:</p>
<ul>
<li><code>useSelector</code> allows us to extract data from the Redux store. Here, we're extracting the <code>count</code> from the state.</li>
<li><code>useDispatch</code> provides access to the <code>dispatch</code> function, allowing us to dispatch actions to the Redux store.</li>
</ul>
<h3 id="heading-pros-of-redux">Pros of Redux</h3>
<ul>
<li><strong>Predictable State Management:</strong> Redux enforces a strict unidirectional data flow, making it predictable and easy to reason about.</li>
<li><strong>Powerful Devtools for Debugging:</strong> Redux comes with powerful browser devtools that allow you to inspect and debug the state changes in your application.</li>
<li><strong>Middleware Support:</strong> Redux supports middleware, enabling you to handle side effects such as asynchronous operations in a clean and organized way.</li>
</ul>
<h3 id="heading-cons-of-redux">Cons of Redux</h3>
<ul>
<li><strong>Boilerplate Code:</strong> Redux often requires writing boilerplate code for actions and reducers, which can be perceived as repetitive.</li>
<li><strong>Steeper Learning Curve:</strong> For beginners, the concepts of actions, reducers, and middleware might present a steeper learning curve compared to simpler state management solutions.</li>
</ul>
<p>Redux is a battle-tested state management library that excels in managing complex state in large applications. While it may introduce some initial complexity and boilerplate, its benefits in terms of predictability, debugging tools, and middleware support make it a powerful choice for scalable projects. </p>
<p>For smaller projects, you might want to consider the trade-offs before opting for Redux, as simpler alternatives like Context API or Recoil might be more suitable.</p>
<h2 id="heading-context-api-simplicity-with-built-in-react-feature">Context API: Simplicity with Built-In React Feature</h2>
<p>The Context API is a part of React itself and provides a way to pass data through the component tree without having to pass props down manually at every level.</p>
<h3 id="heading-how-to-set-up-the-context-api">How to Set Up the Context API</h3>
<p>The Context API in React allows you to share state between components without manually passing props through each level of the component tree. Setting up the Context API involves creating a context and using <code>Provider</code> and <code>Consumer</code> components.</p>
<h4 id="heading-creating-a-context">Creating a Context</h4>
<p>You start by creating a context using the <code>createContext</code> function. This context will hold the state that you want to share.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// AppContext.js</span>
<span class="hljs-keyword">import</span> { createContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> AppContext = createContext();

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AppContext;
</code></pre>
<h4 id="heading-providing-and-consuming-context">Providing and Consuming Context</h4>
<p>You then use the <code>Provider</code> component to wrap the part of your component tree that needs access to the shared state. The <code>Consumer</code> component is used within child components to access the context.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// AppProvider.js</span>
<span class="hljs-keyword">import</span> React, { useReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> AppContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppContext'</span>;

<span class="hljs-keyword">const</span> initialState = { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> };

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AppProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, initialState);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">state</span>, <span class="hljs-attr">dispatch</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>In this example:</p>
<ul>
<li>We have a simple reducer that handles state changes.</li>
<li>The <code>AppProvider</code> component wraps its children with <code>AppContext.Provider</code>, making the context available to all descendants.</li>
<li>The <code>value</code> prop in <code>Provider</code> is set to an object containing the state and a dispatch function.</li>
</ul>
<h4 id="heading-consuming-context-in-a-component">Consuming Context in a Component</h4>
<p>Now, any component within the <code>AppProvider</code> can access the shared state using the <code>useContext</code> hook.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// CounterComponent.js</span>
<span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> AppContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppContext'</span>;

<span class="hljs-keyword">const</span> CounterComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { state, dispatch } = useContext(AppContext);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'INCREMENT' })}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({ type: 'DECREMENT' })}&gt;Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterComponent;
</code></pre>
<h3 id="heading-pros-of-context-api">Pros of Context API</h3>
<ul>
<li><strong>Simplicity and Ease of Use:</strong> The Context API provides a simple and straightforward way to share state between components without the need for additional setup.</li>
<li><strong>No Need for Additional Libraries:</strong> Context API is built into React, eliminating the need for additional libraries, reducing dependencies in your project.</li>
<li><strong>Built-in to React:</strong> Since Context API is a part of React, you can use it without any external dependencies.</li>
</ul>
<h3 id="heading-cons-of-context-api">Cons of Context API</h3>
<ul>
<li><strong>Might Lead to Unnecessary Re-renders:</strong> Context API can cause unnecessary re-renders in components that consume the context, especially if the context value changes frequently. This is due to the lack of optimization mechanisms like memoization.</li>
<li><strong>Limited to Simpler Use Cases:</strong> While suitable for many scenarios, Context API might not provide the same level of control and optimization as dedicated state management libraries like Redux or Recoil.</li>
</ul>
<p>The Context API is a convenient solution for sharing state between components, especially in smaller to medium-sized applications. Its simplicity and built-in nature make it easy to use without introducing additional libraries. Still, you should be mindful of potential re-rendering issues and consider alternative state management solutions for more complex use cases.</p>
<h2 id="heading-recoil-a-fresh-approach-to-state-management">Recoil: A Fresh Approach to State Management</h2>
<p>Recoil is a relatively newer addition to the state management landscape. It's developed by Facebook and is designed to be more flexible and intuitive for managing state in React applications.</p>
<h3 id="heading-how-to-install-recoil">How to Install Recoil</h3>
<p>To use Recoil in a React project, you need to install the <code>recoil</code> package. Open your terminal and run the following command:</p>
<pre><code class="lang-bash">npm install recoil
</code></pre>
<p>This command installs the Recoil library, which is developed by Facebook and designed for state management in React applications.</p>
<h3 id="heading-how-to-set-up-recoil">How to Set Up Recoil</h3>
<p>Recoil introduces the concept of atoms to represent pieces of state and selectors to derive values from that state.</p>
<h4 id="heading-creating-atoms">Creating Atoms</h4>
<p>Atoms are units of state in Recoil. You create atoms to define individual pieces of state that components can read and write to.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// atoms.js</span>
<span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> countState = atom({
  <span class="hljs-attr">key</span>: <span class="hljs-string">'countState'</span>, <span class="hljs-comment">// unique ID (with respect to other atoms/selectors)</span>
  <span class="hljs-attr">default</span>: <span class="hljs-number">0</span>, <span class="hljs-comment">// default value (aka initial value)</span>
});
</code></pre>
<p>In this example, we've created an atom called <code>countState</code> with an initial value of <code>0</code>.</p>
<h4 id="heading-using-atoms-in-components">Using Atoms in Components</h4>
<p>You can use the <code>useRecoilState</code> hook to read and write to atoms in your components.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// CounterComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useRecoilState } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> { countState } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</span>;

<span class="hljs-keyword">const</span> CounterComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [count, setCount] = useRecoilState(countState);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count - 1)}&gt;Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterComponent;
</code></pre>
<p>In the <code>CounterComponent</code>, <code>useRecoilState</code> is used to access the current value of <code>countState</code> and the <code>setCount</code> function to update it.</p>
<h4 id="heading-creating-selectors">Creating Selectors</h4>
<p>Selectors are functions that derive values from one or more atoms or other selectors. They enable the composition of derived state.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// selectors.js</span>
<span class="hljs-keyword">import</span> { selector } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> { countState } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> doubledCount = selector({
  <span class="hljs-attr">key</span>: <span class="hljs-string">'doubledCount'</span>,
  <span class="hljs-attr">get</span>: <span class="hljs-function">(<span class="hljs-params">{ get }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> count = get(countState);
    <span class="hljs-keyword">return</span> count * <span class="hljs-number">2</span>;
  },
});
</code></pre>
<p>In this example, we've created a selector called <code>doubledCount</code> that doubles the value of <code>countState</code>.</p>
<h4 id="heading-using-selectors-in-components">Using Selectors in Components</h4>
<p>You can use the <code>useRecoilValue</code> hook to read values from selectors.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// DoubledCounterComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useRecoilValue } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> { doubledCount } <span class="hljs-keyword">from</span> <span class="hljs-string">'./selectors'</span>;

<span class="hljs-keyword">const</span> DoubledCounterComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> doubledValue = useRecoilValue(doubledCount);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Doubled Count: {doubledValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DoubledCounterComponent;
</code></pre>
<h3 id="heading-pros-of-recoil">Pros of Recoil</h3>
<ul>
<li><strong>Intuitive API with Minimal Boilerplate:</strong> Recoil provides a straightforward API, making it easy to work with state without introducing a lot of boilerplate code.</li>
<li><strong>Automatically Handles Reactivity:</strong> Recoil automatically manages reactivity, ensuring that components update when relevant pieces of state change.</li>
<li><strong>Supports Advanced Features like Selectors:</strong> Recoil supports the creation of selectors, allowing you to derive complex state values based on atoms or other selectors.</li>
</ul>
<h3 id="heading-cons-of-recoil">Cons of Recoil</h3>
<ul>
<li><strong>Relatively New, Limited Community Support:</strong> Being a newer entrant in the state management space, Recoil might not have as extensive community support or third-party packages as more established libraries like Redux.</li>
</ul>
<p>Recoil is a promising state management library that offers a simple yet powerful API for managing state in React applications. It excels in projects that prioritize simplicity, reactivity, and flexibility. </p>
<p>But make sure you consider the maturity of the library and the specific needs of your projects when choosing Recoil over more established alternatives like Redux or Context API. As Recoil evolves and gains more community support, it has the potential to become a go-to solution for state management in React applications.</p>
<h2 id="heading-state-management-with-apis">State Management with APIs</h2>
<p>Now that we have a basic understanding of Redux, Context API, and Recoil, let's explore how each of these solutions handles state in the context of API interactions.</p>
<h3 id="heading-how-to-fetch-data-from-an-api-using-redux">How to Fetch Data from an API Using Redux</h3>
<p>Let's consider a scenario where we need to fetch data from an API and display it in our React application. We'll use the <code>axios</code> library for making API requests.</p>
<p>In this example, we're using Redux to manage the state of the posts fetched from an API.</p>
<h4 id="heading-actionsjs"><code>actions.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-comment">// Action creator for fetching posts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fetchPosts = <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Make a GET request to the API</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);

    <span class="hljs-comment">// Dispatch an action to update the state with the fetched posts</span>
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS'</span>, <span class="hljs-attr">payload</span>: response.data });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-comment">// Dispatch an action in case of an error</span>
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_ERROR'</span>, <span class="hljs-attr">payload</span>: error.message });
  }
};
</code></pre>
<ul>
<li>This file contains an action creator function called <code>fetchPosts</code>.</li>
<li>The action creator is an asynchronous function that dispatches actions based on the result of the API request.</li>
<li>We use <code>axios.get</code> to make a GET request to the specified API endpoint.</li>
<li>If the request is successful, we dispatch an action of type <code>'FETCH_POSTS'</code> with the payload being the data received from the API.</li>
<li>If there's an error during the request, we dispatch an action of type <code>'FETCH_ERROR'</code> with the error message.</li>
</ul>
<h4 id="heading-postsreducerjs"><code>postsReducer.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// postsReducer.js</span>
<span class="hljs-keyword">const</span> postsReducer = <span class="hljs-function">(<span class="hljs-params">state = { posts: [], error: <span class="hljs-literal">null</span> }, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_POSTS'</span>:
      <span class="hljs-comment">// Update the state with the fetched posts and clear any existing error</span>
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">posts</span>: action.payload, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_ERROR'</span>:
      <span class="hljs-comment">// Update the state with an error and an empty array of posts</span>
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">posts</span>: [], <span class="hljs-attr">error</span>: action.payload };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-comment">// Return the current state if the action type doesn't match</span>
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> postsReducer;
</code></pre>
<ul>
<li>This file contains a reducer function named <code>postsReducer</code>.</li>
<li>The reducer takes the current state (which has a <code>posts</code> array and an <code>error</code>) and an action.</li>
<li>In the case where the action type is <code>'FETCH_POSTS'</code>, it updates the state with the fetched posts and clears any existing error.</li>
<li>In the case of <code>'FETCH_ERROR'</code>, it updates the state with an error message and sets the <code>posts</code> array to an empty array.</li>
<li>If the action type doesn't match any of the cases, it returns the current state unchanged.</li>
</ul>
<h4 id="heading-how-it-works">How it Works</h4>
<p><strong>Action Creator (<code>fetchPosts</code>):</strong></p>
<ul>
<li>The <code>fetchPosts</code> action creator is called when you want to initiate the process of fetching posts.</li>
<li>It makes an asynchronous API request using <code>axios.get</code>.</li>
<li>If the request is successful, it dispatches an action of type <code>'FETCH_POSTS'</code> with the fetched data as the payload.</li>
<li>If there's an error, it dispatches an action of type <code>'FETCH_ERROR'</code> with the error message.</li>
</ul>
<p><strong>Reducer (<code>postsReducer</code>):</strong></p>
<ul>
<li>The <code>postsReducer</code> handles the dispatched actions.</li>
<li>When it receives an action of type <code>'FETCH_POSTS'</code>, it updates the state with the fetched posts and clears any existing error.</li>
<li>When it receives an action of type <code>'FETCH_ERROR'</code>, it updates the state with an error message and sets the <code>posts</code> array to an empty array.</li>
<li>If the action type doesn't match any of the cases, it returns the current state unchanged.</li>
</ul>
<p>In the Redux architecture, actions are dispatched to reducers, which then update the application state. This example demonstrates how Redux can be used to manage state changes when fetching data from an API. The state is updated in a predictable way, making it easier to handle different scenarios within the application.</p>
<h3 id="heading-how-to-fetch-data-from-an-api-using-the-context-api">How to Fetch Data from an API Using the Context API:</h3>
<p>In this scenario, the Context API is used to manage the state of the posts fetched from an API and make it accessible to components throughout the React application.</p>
<h4 id="heading-appcontextjs"><code>AppContext.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// AppContext.js</span>
<span class="hljs-keyword">import</span> { createContext, useContext, useReducer, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-comment">// Creating a Context</span>
<span class="hljs-keyword">const</span> AppContext = createContext();

<span class="hljs-comment">// Initial state for the context</span>
<span class="hljs-keyword">const</span> initialState = { <span class="hljs-attr">posts</span>: [], <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };

<span class="hljs-comment">// Reducer function to handle state changes</span>
<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_POSTS'</span>:
      <span class="hljs-comment">// Update state with fetched posts and clear any existing error</span>
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">posts</span>: action.payload, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'FETCH_ERROR'</span>:
      <span class="hljs-comment">// Update state with an error and an empty array of posts</span>
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">posts</span>: [], <span class="hljs-attr">error</span>: action.payload };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-comment">// Return current state if the action type doesn't match</span>
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-comment">// Context Provider component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AppProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-comment">// useReducer hook to manage state and dispatch actions</span>
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, initialState);

  <span class="hljs-comment">// useEffect hook to fetch data when the component mounts</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Make a GET request to the API</span>
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);

        <span class="hljs-comment">// Dispatch an action to update the context state with fetched posts</span>
        dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_POSTS'</span>, <span class="hljs-attr">payload</span>: response.data });
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-comment">// Dispatch an action in case of an error</span>
        dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_ERROR'</span>, <span class="hljs-attr">payload</span>: error.message });
      }
    };

    <span class="hljs-comment">// Fetch data when the component mounts</span>
    fetchData();
  }, []); <span class="hljs-comment">// Empty dependency array to run the effect only once when the component mounts</span>

  <span class="hljs-comment">// Providing the context value to its descendants</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">state</span>, <span class="hljs-attr">dispatch</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-comment">// Custom hook to conveniently consume the context</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useAppContext = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> useContext(AppContext);
};
</code></pre>
<p><strong>Creating a Context:</strong></p>
<ul>
<li><code>createContext</code> is used to create the AppContext, which serves as the container for the state to be shared among components.</li>
</ul>
<p><strong>Initial State and Reducer:</strong></p>
<ul>
<li>The <code>initialState</code> object represents the initial state of the context, including an empty array of posts and no error.</li>
<li>The <code>reducer</code> function handles state changes based on dispatched actions. It updates the state based on the action type.</li>
</ul>
<p><strong>Context Provider (<code>AppProvider</code>):</strong></p>
<ul>
<li>The <code>useReducer</code> hook is used to manage the state and dispatch actions.</li>
<li>The <code>useEffect</code> hook is employed to fetch data when the component mounts (<code>[]</code> as the dependency array ensures it runs only once).</li>
<li>Inside <code>fetchData</code>, Axios is used to make a GET request to the specified API endpoint.</li>
<li>Based on the success or failure of the request, the reducer dispatches actions to update the context state.</li>
</ul>
<p><strong>Context Consumer (<code>useAppContext</code>):</strong></p>
<ul>
<li>The <code>useAppContext</code> custom hook utilizes <code>useContext</code> to conveniently consume the context value within components.</li>
</ul>
<h4 id="heading-how-its-used-in-components">How it's Used in Components:</h4>
<p>Components within the <code>AppProvider</code> can use the <code>useAppContext</code> hook to access the shared state and dispatch actions:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ExampleComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useAppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppContext'</span>;

<span class="hljs-keyword">const</span> ExampleComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Using the custom hook to access the context</span>
  <span class="hljs-keyword">const</span> { state, dispatch } = useAppContext();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Posts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      {state.posts.map((post) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{post.body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
      {state.error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {state.error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExampleComponent;
</code></pre>
<ul>
<li><code>useAppContext</code> is used to consume the context within the <code>ExampleComponent</code>.</li>
<li>The component renders a list of posts if available and displays an error message if there's an error in fetching the data.</li>
</ul>
<p>Context API, along with the use of <code>useReducer</code> and <code>useEffect</code> hooks, allows you to manage and share state across components. The <code>AppProvider</code> sets up the context, fetches data from the API, and updates the context state based on the results. Components within the provider can then use the <code>useAppContext</code> hook to access the shared state and dispatch actions as needed.</p>
<h3 id="heading-how-to-fetch-data-from-an-api-using-recoil">How to Fetch Data from an API Using Recoil:</h3>
<p>In this scenario, Recoil is used to manage the state of posts fetched from an API and make it accessible to components throughout the React application.</p>
<h4 id="heading-atomsjs"><code>atoms.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// atoms.js</span>
<span class="hljs-keyword">import</span> { atom, selector } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-comment">// Atom for posts state</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> postsState = atom({
  <span class="hljs-attr">key</span>: <span class="hljs-string">'postsState'</span>,
  <span class="hljs-attr">default</span>: selector({
    <span class="hljs-attr">key</span>: <span class="hljs-string">'postsState/default'</span>,
    <span class="hljs-attr">get</span>: <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Make a GET request to the API to fetch posts</span>
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);
        <span class="hljs-keyword">return</span> response.data;
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-comment">// Throw an error if the API request fails</span>
        <span class="hljs-keyword">throw</span> error;
      }
    },
  }),
});
</code></pre>
<ul>
<li>The <code>postsState</code> atom is created using Recoil's <code>atom</code> function.</li>
<li>It has a default value defined by a <code>selector</code> that makes an asynchronous API call using <code>axios.get</code>.</li>
<li>If the API call is successful, the fetched data is returned. If an error occurs during the API call, it is thrown.</li>
</ul>
<h4 id="heading-postscomponentjs"><code>PostsComponent.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// PostsComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useRecoilValue } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> { postsState } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</span>;

<span class="hljs-keyword">const</span> PostsComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Using useRecoilValue hook to access the postsState atom</span>
  <span class="hljs-keyword">const</span> posts = useRecoilValue(postsState);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Posts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      {posts.map((post) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{post.body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PostsComponent;
</code></pre>
<ul>
<li>The <code>PostsComponent</code> uses the <code>useRecoilValue</code> hook to access the value of the <code>postsState</code> atom.</li>
<li>It then renders the list of posts, mapping through the array and displaying the title and body of each post.</li>
</ul>
<h4 id="heading-how-its-used-in-components-1">How it's Used in Components:</h4>
<p>Components within the RecoilRoot can use Recoil hooks to read and write to atoms. In this case, <code>useRecoilValue</code> is used to read the value of the <code>postsState</code> atom.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Example of using PostsComponent within a RecoilRoot</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { RecoilRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> PostsComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./PostsComponent'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RecoilRoot</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My React App<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PostsComponent</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RecoilRoot</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>The <code>PostsComponent</code> is used within a <code>RecoilRoot</code>, which is a context provider for Recoil.</li>
<li>This ensures that components within the <code>RecoilRoot</code> can access the Recoil state and use Recoil hooks.</li>
</ul>
<p>Recoil simplifies state management in a React application. In this example, the <code>postsState</code> atom is used to manage the state of posts fetched from an API. The <code>useRecoilValue</code> hook allows components to efficiently read the value of the atom and display the data in the user interface. The structure provided by Recoil allows for a clean and centralized way to manage and share state across components.</p>
<h3 id="heading-how-to-update-data-via-api-using-redux">How to Update Data via API using Redux</h3>
<p>Now, let's explore how each state management solution handles updating data through API requests. We'll start with Redux.</p>
<h4 id="heading-actionsjs-1"><code>actions.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> updatePost = <span class="hljs-function">(<span class="hljs-params">postId, updatedData</span>) =&gt;</span> <span class="hljs-keyword">async</span> (dispatch) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Make a PATCH request to update a specific post by its ID</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.patch(<span class="hljs-string">`https://jsonplaceholder.typicode.com/posts/<span class="hljs-subst">${postId}</span>`</span>, updatedData);

    <span class="hljs-comment">// Dispatch an action to update the state with the updated post</span>
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'UPDATE_POST'</span>, <span class="hljs-attr">payload</span>: response.data });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-comment">// Dispatch an action in case of an error</span>
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_ERROR'</span>, <span class="hljs-attr">payload</span>: error.message });
  }
};
</code></pre>
<ul>
<li>The <code>updatePost</code> action creator is defined to handle updating a post by making a <code>PATCH</code> request to the API.</li>
<li>It takes two parameters: <code>postId</code> (the ID of the post to be updated) and <code>updatedData</code> (the new data for the post).</li>
<li>Upon a successful request, it dispatches an action of type <code>'UPDATE_POST'</code> with the updated post data.</li>
<li>If there's an error during the API request, it dispatches an action of type <code>'FETCH_ERROR'</code> with the error message.</li>
</ul>
<h4 id="heading-postsreducerjs-1"><code>postsReducer.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// postsReducer.js</span>
<span class="hljs-keyword">const</span> postsReducer = <span class="hljs-function">(<span class="hljs-params">state = { posts: [], error: <span class="hljs-literal">null</span> }, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'UPDATE_POST'</span>:
      <span class="hljs-comment">// Update the state with the updated post</span>
      <span class="hljs-keyword">const</span> updatedPosts = state.posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span>
        post.id === action.payload.id ? action.payload : post
      );
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">posts</span>: updatedPosts, <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };
    <span class="hljs-comment">// Other cases...</span>
    <span class="hljs-keyword">default</span>:
      <span class="hljs-comment">// Return the current state if the action type doesn't match</span>
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<ul>
<li>In the <code>postsReducer</code>, a case <code>'UPDATE_POST'</code> is added to handle the update action.</li>
<li>The state is updated by mapping through the existing posts and replacing the one with the matching ID with the updated post.</li>
<li>This ensures that the state is correctly updated with the new data.</li>
</ul>
<p>To use this functionality in a React component, you dispatch the <code>updatePost</code> action, providing the post ID and the updated data. For example:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Example of using updatePost in a React component</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { updatePost } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>;

<span class="hljs-keyword">const</span> UpdatePostComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">const</span> handleUpdatePost = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Example: Updating post with ID 1 and providing new data</span>
    dispatch(updatePost(<span class="hljs-number">1</span>, { <span class="hljs-attr">title</span>: <span class="hljs-string">'Updated Title'</span>, <span class="hljs-attr">body</span>: <span class="hljs-string">'Updated Body'</span> }));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Update Post<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleUpdatePost}</span>&gt;</span>Update Post<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UpdatePostComponent;
</code></pre>
<ul>
<li>The component uses the <code>useDispatch</code> hook to get the <code>dispatch</code> function.</li>
<li>It defines a function <code>handleUpdatePost</code> that dispatches the <code>updatePost</code> action with the post ID (1 in this example) and the updated data.</li>
<li>This function could be triggered by a button click or any other user action.</li>
</ul>
<p>This Redux setup allows for a clean and centralized way to handle updating data through API requests. The action creator (<code>updatePost</code>) is responsible for making the API request, and the reducer (<code>postsReducer</code>) ensures that the state is correctly updated based on the received data. Components can use the <code>useDispatch</code> hook to initiate these updates from the UI.</p>
<h3 id="heading-how-to-update-data-via-api-using-the-context-api">How to Update Data via API Using the Context API:</h3>
<h4 id="heading-appcontextjs-1"><code>AppContext.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// AppContext.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AppProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-comment">// useReducer hook to manage state and dispatch actions</span>
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, initialState);

  <span class="hljs-comment">// Function to update a post via API</span>
  <span class="hljs-keyword">const</span> updatePost = <span class="hljs-keyword">async</span> (postId, updatedData) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Make a PATCH request to update a specific post by its ID</span>
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.patch(<span class="hljs-string">`https://jsonplaceholder.typicode.com/posts/<span class="hljs-subst">${postId}</span>`</span>, updatedData);

      <span class="hljs-comment">// Dispatch an action to update the context state with the updated post</span>
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'UPDATE_POST'</span>, <span class="hljs-attr">payload</span>: response.data });
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// Dispatch an action in case of an error</span>
      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">'FETCH_ERROR'</span>, <span class="hljs-attr">payload</span>: error.message });
    }
  };

  <span class="hljs-comment">// Providing the context value with state, dispatch, and the updatePost function</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">state</span>, <span class="hljs-attr">dispatch</span>, <span class="hljs-attr">updatePost</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<ul>
<li>The <code>updatePost</code> function is added to the context, which makes a <code>PATCH</code> request to update a specific post by its ID.</li>
<li>If the request is successful, it dispatches an action of type <code>'UPDATE_POST'</code> with the updated post data.</li>
<li>In case of an error during the API request, it dispatches an action of type <code>'FETCH_ERROR'</code> with the error message.</li>
<li>The <code>updatePost</code> function is then provided in the context value along with the state and dispatch.</li>
</ul>
<h4 id="heading-how-its-used-in-components-2">How it's Used in Components:</h4>
<p>Components within the <code>AppProvider</code> can use the <code>useContext</code> hook to access the shared state, dispatch, and the <code>updatePost</code> function.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Example of using AppContext in a component</span>
<span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppContext'</span>;

<span class="hljs-keyword">const</span> UpdatePostComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Using useContext hook to access the context value</span>
  <span class="hljs-keyword">const</span> { updatePost } = useContext(AppContext);

  <span class="hljs-keyword">const</span> handleUpdatePost = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Example: Updating post with ID 1 and providing new data</span>
      <span class="hljs-keyword">await</span> updatePost(<span class="hljs-number">1</span>, { <span class="hljs-attr">title</span>: <span class="hljs-string">'Updated Title'</span>, <span class="hljs-attr">body</span>: <span class="hljs-string">'Updated Body'</span> });
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// Handle error if needed</span>
      <span class="hljs-built_in">console</span>.error(error);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Update Post<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleUpdatePost}</span>&gt;</span>Update Post<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UpdatePostComponent;
</code></pre>
<ul>
<li>The <code>UpdatePostComponent</code> uses the <code>useContext</code> hook to access the <code>AppContext</code>.</li>
<li>It extracts the <code>updatePost</code> function from the context value.</li>
<li>The component defines a function <code>handleUpdatePost</code> that calls <code>updatePost</code> with the post ID (1 in this example) and the updated data.</li>
<li>This function could be triggered by a button click or any other user action.</li>
</ul>
<p>Context API, along with the use of <code>useReducer</code> and <code>useContext</code> hooks, provides a way to manage and share state across components. The <code>AppProvider</code> sets up the context, including the ability to update data through API requests. Components within the provider can use the <code>useContext</code> hook to access the shared state, dispatch, and the <code>updatePost</code> function, allowing for a centralized way to handle updates in the application.</p>
<h3 id="heading-how-to-update-data-via-api-using-recoil">How to Update Data via API Using Recoil:</h3>
<h4 id="heading-atomsjs-1"><code>atoms.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// atoms.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> postState = atomFamily({
  <span class="hljs-attr">key</span>: <span class="hljs-string">'postState'</span>,
  <span class="hljs-attr">default</span>: <span class="hljs-function">(<span class="hljs-params">postId</span>) =&gt;</span> selector({
    <span class="hljs-attr">key</span>: <span class="hljs-string">`postState/<span class="hljs-subst">${postId}</span>`</span>,
    <span class="hljs-attr">get</span>: <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Make a GET request to fetch a specific post by its ID</span>
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`https://jsonplaceholder.typicode.com/posts/<span class="hljs-subst">${postId}</span>`</span>);
        <span class="hljs-keyword">return</span> response.data;
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-comment">// Throw an error if the API request fails</span>
        <span class="hljs-keyword">throw</span> error;
      }
    },
  }),
});
</code></pre>
<ul>
<li>The <code>postState</code> is defined as an <code>atomFamily</code>, which allows the creation of separate atoms for each post based on its ID.</li>
<li>Each atom is a <code>selector</code> with a <code>get</code> function that makes a <code>GET</code> request to fetch a specific post by its ID.</li>
<li>If the request is successful, it returns the post data. If there's an error, it throws an error.</li>
</ul>
<h4 id="heading-editpostcomponentjs"><code>EditPostComponent.js</code></h4>
<pre><code class="lang-jsx"><span class="hljs-comment">// EditPostComponent.js</span>
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useRecoilState, useRecoilValue } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> { postState } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</span>;

<span class="hljs-keyword">const</span> EditPostComponent = <span class="hljs-function">(<span class="hljs-params">{ postId }</span>) =&gt;</span> {
  <span class="hljs-comment">// Using useRecoilValue to get the post data</span>
  <span class="hljs-keyword">const</span> post = useRecoilValue(postState(postId));

  <span class="hljs-comment">// Using useRecoilState to get and set the state of the post</span>
  <span class="hljs-keyword">const</span> [updatedTitle, setUpdatedTitle] = useState(post.title);
  <span class="hljs-keyword">const</span> [updatedBody, setUpdatedBody] = useState(post.body);

  <span class="hljs-keyword">const</span> handleUpdate = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Perform a PATCH request to update the specific post by its ID</span>
      <span class="hljs-comment">// with the updated title and body</span>
      <span class="hljs-comment">// Note: Actual API request code is missing in the provided example</span>
      <span class="hljs-comment">// You should implement the API request logic here</span>
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Updating post <span class="hljs-subst">${postId}</span> with title: <span class="hljs-subst">${updatedTitle}</span>, body: <span class="hljs-subst">${updatedBody}</span>`</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// Handle error if needed</span>
      <span class="hljs-built_in">console</span>.error(error);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{updatedTitle}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setUpdatedTitle(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{updatedBody}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setUpdatedBody(e.target.value)} /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleUpdate}</span>&gt;</span>Update Post<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EditPostComponent;
</code></pre>
<ul>
<li>The <code>EditPostComponent</code> uses <code>useRecoilValue</code> to get the current state of the specific post.</li>
<li>It uses <code>useRecoilState</code> to get and set the local state for the updated title and body.</li>
<li>The component renders input fields for the title and body, allowing users to input the updated values.</li>
<li>The <code>handleUpdate</code> function is called when the "Update Post" button is clicked. It should perform a <code>PATCH</code> request to update the specific post with the new title and body. The actual API request logic is missing in the provided example and should be implemented according to the API endpoint.</li>
</ul>
<h4 id="heading-how-its-used-in-components-3">How it's Used in Components:</h4>
<p>To use the <code>EditPostComponent</code> within a RecoilRoot, you render it within a component that is wrapped with <code>RecoilRoot</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Example of using EditPostComponent within a RecoilRoot</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { RecoilRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>;
<span class="hljs-keyword">import</span> EditPostComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./EditPostComponent'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RecoilRoot</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My Recoil App<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">EditPostComponent</span> <span class="hljs-attr">postId</span>=<span class="hljs-string">{1}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RecoilRoot</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>The <code>EditPostComponent</code> is used within a <code>RecoilRoot</code>, which is a context provider for Recoil.</li>
<li>This ensures that components within the <code>RecoilRoot</code> can access the Recoil state and use Recoil hooks.</li>
</ul>
<p>Recoil's <code>atomFamily</code> is used to manage the state of individual posts, and the <code>EditPostComponent</code> demonstrates how to use Recoil hooks to handle updating data through API requests for a specific post. The <code>EditPostComponent</code> allows users to input new values for the title and body, and the <code>handleUpdate</code> function should be extended to include the actual API request logic to update the specific post.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we explored three popular state management solutions for React applications: Redux, Context API, and Recoil. Each has its own strengths and weaknesses, and the choice between them depends on the specific needs and complexity of your project.</p>
<p><strong>Redux:</strong> A battle-tested solution with a predictable state management approach. It excels in managing complex state in large applications but comes with a steeper learning curve and boilerplate code.</p>
<p><strong>Context API:</strong> A built-in React feature that offers simplicity and ease of use. It's suitable for smaller projects or when the complexity of Redux might be overkill.</p>
<p><strong>Recoil:</strong> A relatively newer addition with an intuitive API and flexibility. Recoil is a great choice for projects that prioritize simplicity and reactivity without sacrificing advanced features.</p>
<p>When it comes to handling state in the context of API interactions, all three solutions can be used effectively. Redux with its middleware support, Context API with its simplicity, and Recoil with its reactivity features all provide ways to manage state while interacting with APIs. The key is to choose the one that aligns with your project's requirements and your team's familiarity with the chosen solution.</p>
<p>Remember that the examples provided in this article are simplified, and in real-world applications, additional considerations such as error handling, loading states, and optimization strategies need to be taken into account.</p>
<p>In conclusion, state management is a crucial aspect of building React applications, and understanding the strengths and trade-offs of Redux, Context API, and Recoil will empower you to make informed decisions based on your project's needs. </p>
<p>As the React ecosystem continues to evolve, staying updated on best practices and exploring new solutions will contribute to building more maintainable and scalable applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use React Context in Your Project – Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ As beginners, managing state in React applications can be challenging, especially when passing and utilizing props in deeply nested components.  The usual way of passing information from a main component to its smaller parts — like a parent passing d... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-react-context/</link>
                <guid isPermaLink="false">66bb9055a5fd14123a8b4a20</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React context ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Benedicta Onyebuchi ]]>
                </dc:creator>
                <pubDate>Fri, 05 Jan 2024 20:06:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Learn-With-Benedicta.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As beginners, managing state in React applications can be challenging, especially when passing and utilizing props in deeply nested components. </p>
<p>The usual way of passing information from a main component to its smaller parts — like a parent passing data to a child, then to a grandchild — can get complicated and tiring, especially when we need to access something deep down in the hierarchy.</p>
<p>In this article, we'll explore how the React Context API works, its use cases and a sample project utilizing the concept.</p>
<h2 id="heading-what-is-react-context">What is React Context?</h2>
<p>React Context provides us a way to pass data down through the component tree to where we need it without having to manually pass props at every single level. </p>
<p>It acts as a global storage space for all your components in your project.</p>
<h2 id="heading-how-is-react-context-different-from-prop-threading">How is React Context Different from Prop Threading?</h2>
<p>In prop threading<strong>,</strong> data is passed down from the parent component to the child component. If a child of that component needs the same prop, it is passed down until the required component gets the data. </p>
<p>While simple, it can become complex when traversing deeply nested structures, and this results in prop drilling.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/context-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A pictural representation of prop threading</em></p>
<p>In contrast, React Context allows data to be passed from the parent component to any nested component that requires it, simplifying the process. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Screenshot-2024-01-02-114317.png" alt="Image" width="600" height="400" loading="lazy">
<em>A representation of React context.</em></p>
<h2 id="heading-what-is-prop-drilling">What is Prop Drilling?</h2>
<p>Prop drilling refers to a situation where this threading of props becomes complicated due to the need to pass them through multiple layers of components. </p>
<p>As the data is passed down through many layers, each intermediate component needs to receive and pass the data, even if it doesn't use the data itself.</p>
<p>Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> GrandchildComponent = <span class="hljs-function">(<span class="hljs-params">{ dataFromChild }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Username in Grandchild: {dataFromChild.username}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">{ dataFromParent }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Your email: {dataFromParent.email}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">GrandchildComponent</span> <span class="hljs-attr">dataFromChild</span>=<span class="hljs-string">{dataFromParent}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [userData, setUserData] = useState({
    <span class="hljs-attr">username</span>: <span class="hljs-string">'benny_dicta'</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">'benedictaonyebuchi@gmail.com'</span>,
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome, {userData.username}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">dataFromParent</span>=<span class="hljs-string">{userData}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ParentComponent</span> /&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>The code above shows a typical case of prop drilling where data is passed from the <code>ParentComponent</code> to the <code>GrandChild</code> component even when they are not needed by that component.</p>
<ul>
<li><code>ParentComponent</code> is the top-level component that holds some data (<code>userData</code>).</li>
<li><code>ChildComponent</code> is a child of <code>ParentComponent</code> and receives <code>dataFromParent</code> as a prop. It also renders a <code>GrandChildComponent</code>, passing the received prop further down.</li>
<li><code>GrandChildComponent</code> is deeply nested and receives the prop <code>dataFromChild</code>. It renders the data in its UI.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Screenshot-2024-01-02-115808.png" alt="Image" width="600" height="400" loading="lazy">
<em>A representation of a simple project structure</em></p>
<h2 id="heading-when-to-choose-react-context">When to choose React Context</h2>
<ul>
<li>For simple and straightforward projects, prop threading would be adequate.</li>
<li>For complex projects requiring data to traverse multiple nested layers, React Context provides a cleaner solution.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Screenshot-2024-01-02-120902.png" alt="Image" width="600" height="400" loading="lazy">
<em>A representation of a deeply nested application</em></p>
<p>The pictural difference between both approaches can be seen here. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Screenshot-2024-01-02-124809.png" alt="Image" width="600" height="400" loading="lazy">
<em>A pictural representation of the difference between react context and prop drilling.</em></p>
<h2 id="heading-what-are-the-use-cases-for-react-context-api">What are the Use Cases for React Context API?</h2>
<p>Here are some of the use cases for React Context:</p>
<ol>
<li>When prop drilling becomes complicated: Imagine having to pass a prop through multiple layers of components just to reach the one that needs it. Context API eliminates this prop-drilling headache.</li>
<li>Global data requirement: When multiple components need access to the same data (for example: user authentication status, theme preferences, and so on), using context makes it accessible without redundant prop passing.</li>
<li>Themable components: If your application requires changing themes, like light and dark modes, and you want components deep in the tree to adapt dynamically to theme changes, Context API makes this seamless.</li>
<li>Multi-level nesting: In deeply nested component trees, passing props down the hierarchy becomes impractical. Context provides a cleaner solution for sharing data across various levels.</li>
</ol>
<h2 id="heading-how-to-use-react-context-api">How to use React Context API</h2>
<h4 id="heading-step-1-create-a-context">Step #1 - Create a Context</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MyContext = createContext();
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyContext;
</code></pre>
<h4 id="heading-step-2-wrap-your-app-with-context-provider">Step #2 - Wrap your App with Context Provider</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> MyContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./MyContext'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sharedValue = <span class="hljs-string">'This is a shared value'</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{sharedValue}</span>&gt;</span>
      {/* Your components go here */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">MyContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h4 id="heading-step-3-consume-the-context-in-components">Step #3 - Consume the Context in Components</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> MyContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./MyContext'</span>;

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sharedValue = useContext(MyContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{sharedValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyComponent;
</code></pre>
<h2 id="heading-the-three-important-parts-of-the-react-context-api">The three Important Parts of the React Context API.</h2>
<p>In this section, we'll talk about the three important parts of the React Context API: Provide, Context, and Consumer.</p>
<h3 id="heading-provider">Provider</h3>
<p>This is a component that is used to wrap components in order to access to the context's value. This is where you pass the values that you want to share throughout the component tree using the <code>value</code> prop. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> MyContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./MyContext'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sharedValue = <span class="hljs-string">'This is a shared value'</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{sharedValue}</span>&gt;</span>
     {children} {/*all components in its subtree*/}
    <span class="hljs-tag">&lt;/<span class="hljs-name">MyContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the code above, the context is imported and the <code>.Provider</code> appended to the context, <code>MyContext</code>. This makes the prop passed to the Provider available to all of its children. That is, the components in its subtree.</p>
<h3 id="heading-context">Context</h3>
<p>This acts as the storage where the data is stored. It comes with two parts:</p>
<ul>
<li><code>createContext()</code> — This creates the global object and creates the context.</li>
<li><code>useContext()</code> — This consumes the information made available by the provider.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">/*MyComponent.js*/</span>

<span class="hljs-keyword">import</span> React, { createContext, useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MyContext = createContext();

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sharedValue = useContext(MyContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{sharedValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyComponent;
</code></pre>
<p>In the code above, the Context is created by assigning the imported <code>useContext</code> hook to the <code>MyComponent</code> function.</p>
<h3 id="heading-consumer">Consumer</h3>
<p>The Consumer component is used to consume the shared data within a component. It allows components to subscribe to the context changes and access the shared value. We might not see the consumer per say but it will use the information rendered by the provider. </p>
<p>It must always be nested inside the Provider because the Provider will render first to pass data to the components consuming the data. In otherwords, it must exist before you can consume it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> MyContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./MyComponent'</span>;

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sharedValue = useContext(MyContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{sharedValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyComponent;
</code></pre>
<p>In the code, the <code>MyComponent</code> component utilizes the <code>MyContext</code> context created earlier by using the <code>useContext</code>.</p>
<h2 id="heading-how-to-create-a-theme-switching-app-using-react-context">How to Create a Theme-Switching App using React Context.</h2>
<p>Let's implement a simple theme-switching application using React Context API.</p>
<h4 id="heading-step-1">Step #1</h4>
<p>In the <strong>src</strong> folder create a <strong>context</strong> folder. Then create a new file called <code>ThemeContext.js</code>. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { createContext, useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> ThemeContext = createContext();

<span class="hljs-keyword">const</span> ThemeProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">'light'</span>);

  <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> {
    setTheme(<span class="hljs-function">(<span class="hljs-params">prevTheme</span>) =&gt;</span> (prevTheme === <span class="hljs-string">'light'</span> ? <span class="hljs-string">'dark'</span> : <span class="hljs-string">'light'</span>));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">theme</span>, <span class="hljs-attr">toggleTheme</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> useTheme = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> useContext(ThemeContext);
};

<span class="hljs-keyword">export</span> { ThemeProvider, useTheme };
</code></pre>
<h5 id="heading-walkthrough">Walkthrough:</h5>
<ul>
<li>We started by creating a context (<code>createContext()</code>) and assigning a <code>ThemeContext</code> variable to it, which will act as storage for the theme data.</li>
<li>In the <code>ThemeProvider</code> component, we used the <code>useState</code> hook to manage current theme and also create a toggle that will help with switching between light and dark mode.</li>
<li>The <code>&lt;ThemeContext.Provider&gt;</code> wraps the children, making the props passed to it available to every component within its subtree.</li>
<li>The <code>useTheme</code> component is a custom hook that uses <code>useContext()</code> to consume the <code>ThemeContext</code> context.</li>
</ul>
<h4 id="heading-step-2">Step #2</h4>
<p>In your <strong>src</strong> folder create a <code>ThemedComponent.js</code> file. Copy and paste the code below in the file:</p>
<pre><code class="lang-javscript">import React from 'react';
import { useTheme } from './context/ThemeContext';

const ThemedComponent = () =&gt; {
  const { theme, toggleTheme } = useTheme();

  return (
    &lt;div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#333' : '#fff' }}&gt;
      &lt;h2&gt;Themed Component&lt;/h2&gt;
      &lt;p&gt;Current Theme: {theme}&lt;/p&gt;
      &lt;button onClick={toggleTheme}&gt;Toggle Theme&lt;/button&gt;
    &lt;/div&gt;
  );
};

export default ThemedComponent;
</code></pre>
<h5 id="heading-walkthrough-1">Walkthrough:</h5>
<ul>
<li>Using the <code>useTheme()</code> hook, you can get access to consume the theme context. Remember that we passed  <code>theme</code> and the <code>toggleTheme</code> function to the <code>ThemeContext.Provider</code>.</li>
<li>The component's style dynamically changes based on the current theme. This shows how components can adapt to global state changes managed by the context.</li>
<li>The button triggers the <code>toggleTheme</code> function to switch between light and dark mode.</li>
</ul>
<h4 id="heading-step-3">Step #3</h4>
<p>In your <code>App.js</code> file, copy and paste the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { ThemeProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'./context/ThemeContext'</span>;
<span class="hljs-keyword">import</span> ThemedComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./ThemedComponent.js'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Themed App<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ThemedComponent</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h5 id="heading-walkthrough-2">Walkthrough:</h5>
<ul>
<li><code>&lt;App /&gt;</code> is the main app component where the <code>ThemeProvider</code> is used to wrap the whole application and give theme context access to all components within the <code>ThemeProvider</code>.</li>
<li>The <code>ThemedComponent</code> is rendered, showcasing the result of the components with access to the context.</li>
</ul>
<p>After successful implementation of context, the result should be like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/ezgif.com-video-to-gif-converter.gif" alt="Image" width="600" height="400" loading="lazy">
<em>A simple theme switch using react context.</em></p>
<p>This should help you implement the React Context API in your project.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about context, context provider, context consumer, and how to create a React provider wrapper that manages the value of a context through component state. </p>
<p>You also learned about prop threading, prop drilling and its disadvantage relative to React context. </p>
<p>Finally, you learned how to retrieve values from a context using the <code>useContext</code> hook by building a simple theme switcher.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://react.dev/reference/react/createContext">Official React Documentation on Context API</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=6RhOzQciVwI">React Context and Hooks - Video Tutorial</a></li>
</ul>
<p>Thanks for Reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Secure User Authentication Flow in Flutter with Firebase and Bloc State Management ]]>
                </title>
                <description>
                    <![CDATA[ User authentication is critical to mobile app development. It helps make sure that only authorized users can access sensitive information and perform actions within an application. In this tutorial, we will explore how to build secure user authentica... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/user-authentication-flow-in-flutter-with-firebase-and-bloc/</link>
                <guid isPermaLink="false">66be1f69a1b2d9ba40be180e</guid>
                
                    <category>
                        <![CDATA[ BLoC ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Firebase ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Justice Nwogu ]]>
                </dc:creator>
                <pubDate>Tue, 21 Nov 2023 15:21:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/Group-1--3-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>User authentication is critical to mobile app development. It helps make sure that only authorized users can access sensitive information and perform actions within an application.</p>
<p>In this tutorial, we will explore how to build secure user authentication in Flutter using Firebase for authentication and the Bloc state management pattern for handling application state. By the end, you'll have a solid understanding of how to integrate Firebase authentication and implement a secure login and sign-up process using Bloc.</p>
<h3 id="heading-prerequisites">Prerequisites:</h3>
<p>To get the most out of this tutorial, you should have the following:</p>
<ul>
<li>A good understanding of Flutter and Dart</li>
<li>A Firebase account: Create a Firebase account if you don't have one. You can set up a Firebase project through the <a target="_blank" href="https://console.firebase.google.com/">Firebase Console</a>.</li>
</ul>
<h2 id="heading-how-firebase-authentication-works"><strong>How Firebase Authentication Works</strong></h2>
<p>Firebase Authentication is a powerful service that simplifies the process of authenticating users in your app. It supports various authentication methods, including email/password, social media, and more.</p>
<p>One of the key advantages of Firebase Authentication is its built-in security features, such as secure storage of user credentials and encryption of sensitive data.</p>
<h2 id="heading-flowchart-description"><strong>FlowChart Description</strong></h2>
<p>Let's visualize the flow of actions using a flowchart to understand the concept you are going to learn. Take a look at the diagram below to get a better understanding:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Flowcharts.png" alt="Image" width="600" height="400" loading="lazy">
<em>Img 1: The flowchart of the app</em></p>
<p>The image above is a flowchart to visualize the flow of the app let's discuss what each parts represents. The rounded rectangles represent the starting and ending points of the flow; the purple rectangles represent the screens; the light blue rectangles represent the processes that take place; and finally, the rhombus represents decision-making.</p>
<ul>
<li>The application starts at the <code>AuthenticationFlowScreen</code>.</li>
<li>The <code>StreamBuilder</code> listens to authentication state changes.</li>
<li>If a user is authenticated, it directs to the <code>HomeScreen</code>; otherwise, it leads to the <code>SignupScreen</code>.</li>
<li><code>AuthenticationBloc</code> manages user authentication events and states.</li>
<li>When the user signs up (<code>SignUpUser</code> event is triggered):</li>
<li>It initiates the authentication loading state (<code>AuthenticationLoadingState</code>).</li>
<li>Calls <code>signUpUser</code> from <code>AuthService</code> for user registration.</li>
<li>If successful, it emits  <code>AuthenticationSuccessState</code> with user data; otherwise, emits <code>AuthenticationFailureState</code>.</li>
<li>When the user initiates the sign-out process (<code>SignOut</code> event is triggered):</li>
<li>It starts the authentication loading state (<code>AuthenticationLoadingState</code>).</li>
<li>Calls <code>signOutUser</code> from <code>AuthService</code> to sign the user out.</li>
<li>If an error occurs during sign-out, it logs the error message.</li>
</ul>
<h2 id="heading-project-setup"><strong>Project Setup</strong></h2>
<p>To get started with Firebase Authentication, you must set up Firebase in your Flutter project.</p>
<p>Follow these steps to add Firebase and bloc to your project:</p>
<h3 id="heading-add-dependencies-to-your-project">Add Dependencies to Your Project</h3>
<p>Open your project in your preferred code editor.</p>
<p>Add the following dependencies to your <code>pubspec.yaml</code> file:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
<span class="hljs-attr">firebase_core:</span> <span class="hljs-string">^2.20.0</span>
<span class="hljs-attr">firebase_auth:</span> <span class="hljs-string">^4.12.0</span>
<span class="hljs-attr">flutter_bloc:</span> <span class="hljs-string">^8.1.3</span>
</code></pre>
<p>Then save the <code>pubspec.yaml</code> file to fetch the dependencies.</p>
<h3 id="heading-configure-firebase">Configure Firebase</h3>
<p>Create a new Firebase project through the Firebase <a target="_blank" href="https://www.freecodecamp.org/news/p/9b9114d1-6fce-4349-a755-fdaa04b2d4ae/console.firebase.google.com">Console</a>. Click on authentication in the project, and follow the provided instructions.</p>
<p>For more information, you can go through the Firebase <a target="_blank" href="https://firebase.google.com/docs/auth">website</a>.</p>
<h3 id="heading-initialize-firebase">Initialize Firebase</h3>
<p>First, open the <code>main.dart</code> file in the <code>lib</code> folder.</p>
<p>Add the following code to the file to initialize Firebase:</p>
<pre><code class="lang-dart">
<span class="hljs-keyword">void</span> main() <span class="hljs-keyword">async</span> {
WidgetsFlutterBinding.ensureInitialized();
<span class="hljs-keyword">await</span> Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform
);
</code></pre>
<p>The code above shows the code for running the app. There's nothing unusual about this code except that we have added some code to the <code>void main</code> to initialize Firebase.</p>
<h3 id="heading-the-user-model">The User Model</h3>
<p>Before creating the Firebase class to communicate with the Firebase service, let's define a UserModel to represent the user data.</p>
<p>Start by creating a <code>user.dart</code> file in your project's <code>lib</code> directory.</p>
<p>Then add the code below in the file:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserModel</span> </span>{
<span class="hljs-keyword">final</span> <span class="hljs-built_in">String?</span> id;
<span class="hljs-keyword">final</span> <span class="hljs-built_in">String?</span> email;
<span class="hljs-keyword">final</span> <span class="hljs-built_in">String?</span> displayName;
UserModel({ <span class="hljs-keyword">this</span>.id, <span class="hljs-keyword">this</span>.email, <span class="hljs-keyword">this</span>.displayName, });
}
</code></pre>
<p>Now that you have set up Firebase and created a user model, you need to create a service class to communicate with Firebase directly.</p>
<h3 id="heading-the-authentication-service">The Authentication Service</h3>
<p> Create a folder called <code>services</code>, create a file in this folder called <code>authentication.dart</code> You can now add this code to the file.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_auth/firebase_auth.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../models/user.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthService</span> </span>{
  <span class="hljs-keyword">final</span> FirebaseAuth _firebaseAuth = FirebaseAuth.instance;


  <span class="hljs-comment">/// <span class="markdown">create user</span></span>
  Future&lt;UserModel?&gt; signUpUser(
    <span class="hljs-built_in">String</span> email,
    <span class="hljs-built_in">String</span> password,
  ) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> UserCredential userCredential =
          <span class="hljs-keyword">await</span> _firebaseAuth.createUserWithEmailAndPassword(
        email: email.trim(),
        password: password.trim(),
      );
      <span class="hljs-keyword">final</span> User? firebaseUser = userCredential.user;
      <span class="hljs-keyword">if</span> (firebaseUser != <span class="hljs-keyword">null</span>) {
        <span class="hljs-keyword">return</span> UserModel(
          id: firebaseUser.uid,
          email: firebaseUser.email ?? <span class="hljs-string">''</span>,
          displayName: firebaseUser.displayName ?? <span class="hljs-string">''</span>,
        );
      }
    } <span class="hljs-keyword">on</span> FirebaseAuthException <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-built_in">print</span>(e.toString());
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
  } 

   <span class="hljs-comment">///<span class="markdown">signOutUser </span></span>
   Future&lt;<span class="hljs-keyword">void</span>&gt; signOutUser() <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">final</span> User? firebaseUser = FirebaseAuth.instance.currentUser;
    <span class="hljs-keyword">if</span> (firebaseUser != <span class="hljs-keyword">null</span>) {
      <span class="hljs-keyword">await</span> FirebaseAuth.instance.signOut();
    }
  }
  <span class="hljs-comment">// ... (other methods)}</span>
}
</code></pre>
<p>The code snippet above is a method to create a user in the app using Firebase. With this method, the <code>signUpUser</code> method takes two string parameters: <code>email</code> and <code>password</code> respectively. Then you call the Firebase method to create a user using the parameters we added.</p>
<p>Now that you know how to create the signup method, you can also create the login method. The class ultimately portrays the communication between Firebase and the app.</p>
<p>The next part is to connect the service to your state management, which we'll see how to do now.</p>
<h2 id="heading-how-bloc-state-management-works"><strong>How Bloc State Management Works</strong></h2>
<p>Bloc is a popular state management pattern for Flutter that helps manage complex application states predictably and in a testable way. Bloc stands for "<strong>Business Logic Component</strong>" and it divides the business logic and the UI. Bloc will be the bridge between your app and Firebase.</p>
<p>There's an extension for <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=FelixAngelov.bloc">VScode</a> that creates the boilerplate code for Bloc. You can use the extension to speed up the development process.</p>
<h3 id="heading-set-up-firebase-authentication-bloc">Set Up Firebase Authentication Bloc</h3>
<p>Bloc consists of events and states. Let's first create the states and events for the Bloc. Then we'll create a <code>AuthenticationBloc</code> that will handle the logic using the events, states, and service we have created.</p>
<h4 id="heading-the-authenticationstate-class">The <code>AuthenticationState</code> class</h4>
<p>The <code>AuthenticationState</code> class is responsible for the authentication process's different states. As we will see in the code, there are initial, loading, success, and failure states to ensure we know what happens during the authentication process.</p>
<p>First, create an <code>authentication_state.dart</code> file in your project's <code>bloc</code> directory.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">part</span> of <span class="hljs-string">'authentication_bloc.dart'</span>;


<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationState</span> </span>{
  <span class="hljs-keyword">const</span> AuthenticationState();

  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [];
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationInitialState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationState</span> </span>{}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationLoadingState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationState</span> </span>{
 <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> isLoading;

  AuthenticationLoadingState({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.isLoading});
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationSuccessState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationState</span> </span>{
  <span class="hljs-keyword">final</span> UserModel user;

  <span class="hljs-keyword">const</span> AuthenticationSuccessState(<span class="hljs-keyword">this</span>.user);
  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [user];
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationFailureState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationState</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> errorMessage;

  <span class="hljs-keyword">const</span> AuthenticationFailureState(<span class="hljs-keyword">this</span>.errorMessage);

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [errorMessage];
}
</code></pre>
<p>Let's break down the code:</p>
<p><code>AuthenticationState</code> abstract class:</p>
<ul>
<li><code>AuthenticationState</code> is the base class for different states where the authentication process can be at any time.</li>
<li>It contains a method <code>props</code> that returns a list of objects. This method is used for equality checking when comparing instances of this class.</li>
</ul>
<p><code>AuthenticationInitialState</code> class:</p>
<ul>
<li><code>AuthenticationInitialState</code> represents the initial state of the authentication process.</li>
</ul>
<p><code>AuthenticationLoadingState</code> class:</p>
<ul>
<li><code>AuthenticationLoadingState</code> represents a state where the authentication process is in progress, and the UI might show a loading indicator.</li>
<li>It takes a boolean parameter, <code>isLoading</code>, to indicate whether or not the authentication process is currently loading.</li>
</ul>
<p><code>AuthenticationSuccessState</code> class:</p>
<ul>
<li><code>AuthenticationSuccessState</code> represents a state where the authentication process has been completed.</li>
<li>It includes a user property of type UserModel representing the authenticated user.</li>
</ul>
<p><code>AuthenticationFailureState</code> class:</p>
<ul>
<li><code>AuthenticationFailureState</code>  represents a state where the authentication process has failed.</li>
<li>It includes an <code>error message</code> property containing information about the failure.</li>
</ul>
<h4 id="heading-the-authenticationevent-class">The <code>AuthenticationEvent</code> class</h4>
<p>The <code>AuthenticationEvent</code> is responsible for the events the <code>AuthenticationBloc</code> will perform. In this case, it is the sign-in event. You can write the other events, like sign-up and sign-out, here.</p>
<p>Create a <code>authentication_Event.dart</code> file in your project's <code>bloc</code> directory.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">part</span> of <span class="hljs-string">'authentication_bloc.dart'</span>;



<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationEvent</span> </span>{
  <span class="hljs-keyword">const</span> AuthenticationEvent();

  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [];

}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignUpUser</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationEvent</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> email;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> password;

  <span class="hljs-keyword">const</span> SignUpUser(<span class="hljs-keyword">this</span>.email, <span class="hljs-keyword">this</span>.password);

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [email, password];
}


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignOut</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AuthenticationEvent</span> </span>{}
</code></pre>
<p>The <code>AuthenticationEvent</code> class is similar to <code>AuthenticationState</code>. Let's look at the code to see what it's doing:</p>
<p><code>AuthenticationEvent</code> abstract class:</p>
<ul>
<li>This is the base class for different events that trigger authentication state changes.</li>
</ul>
<p><code>SignUpUser</code> class:</p>
<ul>
<li>This class represents an event where a user is attempting to sign up.</li>
<li>It takes two parameters, <code>email</code> and <code>password</code>, representing the credentials the user is using to sign up.</li>
<li>This class's instances will signal the <code>Bloc</code> that a user is trying to sign up, and the <code>Bloc</code> can respond by initiating the sign-up process and transitioning the authentication state accordingly.</li>
</ul>
<p><code>SignOut</code> class:</p>
<ul>
<li>This class's instances will signal the <code>Bloc</code> that a user is trying to sign out. The <code>bloc</code> can respond by initiating the sign-out process and updating the authentication state accordingly.</li>
</ul>
<h4 id="heading-the-authenticationbloc-class">The <code>AuthenticationBloc</code> class</h4>
<p>The <code>AuthenticationBloc</code> will handle the overall authentication state, from what happens when a user clicks a button to what shows on the screen. It also interacts with the Firebase service we created directly.</p>
<p>First, create a file called <code>authentication_bloc.dart</code> in your project's <code>bloc</code> directory.</p>
<p>Add the following code to define the <code>AuthenticationBloc</code> class:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:bloc/bloc.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:meta/meta.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../models/user.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../services/authentication.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'authentication_event.dart'</span>;
<span class="hljs-keyword">part</span> <span class="hljs-string">'authentication_state.dart'</span>;



<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationBloc</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bloc</span>&lt;<span class="hljs-title">AuthenticationEvent</span>, <span class="hljs-title">AuthenticationState</span>&gt; </span>{
  <span class="hljs-keyword">final</span> AuthService authService = AuthService();

  AuthenticationBloc() : <span class="hljs-keyword">super</span>(AuthenticationInitialState()) {
    <span class="hljs-keyword">on</span>&lt;AuthenticationEvent&gt;((event, emit) {});

    <span class="hljs-keyword">on</span>&lt;SignUpUser&gt;((event, emit) <span class="hljs-keyword">async</span> {
      emit(AuthenticationLoadingState(isLoading: <span class="hljs-keyword">true</span>));
      <span class="hljs-keyword">try</span> {
          <span class="hljs-keyword">final</span> UserModel? user =
          <span class="hljs-keyword">await</span> authService.signUpUser(event.email, event.password);
      <span class="hljs-keyword">if</span> (user != <span class="hljs-keyword">null</span>) {
        emit(AuthenticationSuccessState(user));

      } <span class="hljs-keyword">else</span> {
        emit(<span class="hljs-keyword">const</span> AuthenticationFailureState(<span class="hljs-string">'create user failed'</span>));
      }
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-built_in">print</span>(e.toString());
      }
     emit(AuthenticationLoadingState(isLoading: <span class="hljs-keyword">false</span>));
    });

     <span class="hljs-keyword">on</span>&lt;SignOut&gt;((event, emit) <span class="hljs-keyword">async</span> {
      emit(AuthenticationLoadingState(isLoading: <span class="hljs-keyword">true</span>));
      <span class="hljs-keyword">try</span> {
        authService.signOutUser();
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">'error'</span>);
        <span class="hljs-built_in">print</span>(e.toString());
      } 
       emit(AuthenticationLoadingState(isLoading: <span class="hljs-keyword">false</span>));
     });
}
}
</code></pre>
<p>In this code snippet, we have created an instance of the <code>AuthService</code> class, which handles user authentication operations, such as signing up and signing out.</p>
<p><code>on&lt;SignUpUser&gt;((event, emit) async { ... }</code> defines a handler for the <code>SignUpUser</code> event. When this event is triggered, the <code>bloc</code> goes through the following steps:</p>
<ul>
<li>It emits an  <code>AuthenticationLoadingState</code> to indicate that the authentication process is in progress.</li>
<li>It calls for the <code>signUpUser</code> method of the  <code>authService</code> to attempt to create a user account with the provided email and password.</li>
<li>If the user account creation is successful (that is, the user is not null), it emits an  <code>AuthenticationSuccessState</code> with the user data.</li>
<li>If the user account creation fails, it emits an <code>AuthenticationFailureState</code> with an error message and logs the error.</li>
<li>Regardless of success or failure, it emits another <code>AuthenticationLoadingState</code> to signal the end of the authentication process.</li>
</ul>
<p><code>on&lt;SignOut&gt;((event, emit) async { ... }</code> defines a handler for the <code>SignOut</code>  event. When this event is triggered, the <code>bloc</code> goes through the following steps:</p>
<ul>
<li>It emits an <code>AuthenticationLoadingState</code> to indicate that the sign-out process is in progress.</li>
<li>It calls the <code>signOutUser</code> method of the <code>authService</code> to sign the user out.</li>
<li>If any errors occur during the sign-out process, it logs the error.</li>
<li>It emits another <code>AuthenticationLoadingState</code> to signal the end of the sign-out process.</li>
</ul>
<p>The <code>AuthenticationBloc</code> manages the state of the authentication process, including loading, success, and failure states, based on the events triggered by user actions. The <code>authService</code> is responsible for carrying out the actual authentication operations.  </p>
<p>With the Bloc set up, we can implement the authentication flow using Bloc.</p>
<h2 id="heading-how-to-implement-the-authentication-flow-with-bloc"><strong>How to Implement the Authentication Flow with Bloc</strong></h2>
<p>To implement the authentication flow, you will create a dedicated Stateless widget to check if a user has logged in already so that we will know what screen to show the user. The page will display different screens based on the user's authentication state.</p>
<h3 id="heading-authenticationflowscreen"><code>AuthenticationFlowScreen</code>:</h3>
<p>Create a new file called <code>authentication_page.dart</code> in your project's <code>screens</code> directory.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:bloc_authentication_flow/screens/home.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:bloc_authentication_flow/screens/sign_up.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_auth/firebase_auth.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthenticationFlowScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> AuthenticationFlowScreen({<span class="hljs-keyword">super</span>.key});
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> id = <span class="hljs-string">'main screen'</span>;
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      body: StreamBuilder&lt;User?&gt;(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (context, snapshot) {
          <span class="hljs-keyword">if</span> (snapshot.hasData) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">const</span> HomeScreen();
          } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">const</span> SignupScreen();
          }
        },
      ),
    );
  }
}
</code></pre>
<p>In the above code, you have a <code>StatelessWidget</code> with a <code>StreamBuilder</code> as the child. The <code>StreamBuilder</code> acts as a judge, using Firebase to check the state changes and if a user has logged in or not. If a user has logged in, it directs them to the home screen, else it goes to the sign-up screen.</p>
<p>Change the home route to <code>AuthenticationFlowScreen</code> to allow the app to check before routing to any page.</p>
<pre><code class="lang-dart">   home: <span class="hljs-keyword">const</span> AuthenticationFlowScreen()
</code></pre>
<h3 id="heading-sign-up-screen">Sign-up Screen</h3>
<p>First, create a new file called <code>sign_up.dart</code> in the <code>screens</code> directory.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:bloc_authentication_flow/screens/home.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter_bloc/flutter_bloc.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../bloc/authentication_bloc.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignupScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> id = <span class="hljs-string">'login_screen'</span>;

  <span class="hljs-keyword">const</span> SignupScreen({
    Key? key,
  }) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  State&lt;SignupScreen&gt; createState() =&gt; _SignupScreenState();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_SignupScreenState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State</span>&lt;<span class="hljs-title">SignupScreen</span>&gt; </span>{
  <span class="hljs-comment">// Text Controllers</span>
  <span class="hljs-keyword">final</span> emailController = TextEditingController();
  <span class="hljs-keyword">final</span> passwordController = TextEditingController();

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> dispose() {
    emailController.dispose();
    passwordController.dispose();
    <span class="hljs-keyword">super</span>.dispose();
  }

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(
        title: <span class="hljs-keyword">const</span> Text(
          <span class="hljs-string">'Login to Your Account'</span>,
          style: TextStyle(
            color: Colors.deepPurple,
          ),
        ),
        centerTitle: <span class="hljs-keyword">true</span>,
      ),
      body: Padding(
        padding: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">16.0</span>),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">20</span>),
            <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Email address'</span>),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">10</span>),
            TextFormField(
              controller: emailController,
              decoration: <span class="hljs-keyword">const</span> InputDecoration(
                border: OutlineInputBorder(),
                hintText: <span class="hljs-string">'Enter your email'</span>,
              ),
            ),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">10</span>),
            <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Password'</span>),
            TextFormField(
              controller: passwordController,
              decoration: <span class="hljs-keyword">const</span> InputDecoration(
                border: OutlineInputBorder(),
                hintText: <span class="hljs-string">'Enter your password'</span>,
              ),
              obscureText: <span class="hljs-keyword">false</span>,
            ),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">10</span>),
            GestureDetector(
              onTap: () {},
              child: <span class="hljs-keyword">const</span> Text(
                <span class="hljs-string">'Forgot password?'</span>,
                style: TextStyle(
                  color: Colors.deepPurple,
                ),
              ),
            ),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">20</span>),
            BlocConsumer&lt;AuthenticationBloc, AuthenticationState&gt;(
              listener: (context, state) {
                <span class="hljs-keyword">if</span> (state <span class="hljs-keyword">is</span> AuthenticationSuccessState) {
                  Navigator.pushNamedAndRemoveUntil(
                    context,
                    HomeScreen.id,
                    (route) =&gt; <span class="hljs-keyword">false</span>,
                  );
                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (state <span class="hljs-keyword">is</span> AuthenticationFailureState) {
                  showDialog(
                      context: context,
                      builder: (context) {
                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">const</span> AlertDialog(
                          content: Text(<span class="hljs-string">'error'</span>),
                        );
                      });
                }
              },
              builder: (context, state) {
                <span class="hljs-keyword">return</span> SizedBox(
                  height: <span class="hljs-number">50</span>,
                  width: <span class="hljs-built_in">double</span>.infinity,
                  child: ElevatedButton(
                    onPressed: () {
                      BlocProvider.of&lt;AuthenticationBloc&gt;(context).add(
                        SignUpUser(
                          emailController.text.trim(),
                          passwordController.text.trim(),
                        ),
                      );
                    },
                    child:  Text(
                      state <span class="hljs-keyword">is</span> AuthenticationLoadingState
                            ? <span class="hljs-string">'.......'</span>,
                            : <span class="hljs-string">'Signup'</span>,
                      style: TextStyle(
                        fontSize: <span class="hljs-number">20</span>,
                      ),
                    ),
                  ),
                );
              },
            ),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">20</span>),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                <span class="hljs-keyword">const</span> Text(<span class="hljs-string">"Already have an account? "</span>),
                GestureDetector(
                  onTap: () {},
                  child: <span class="hljs-keyword">const</span> Text(
                    <span class="hljs-string">'Login'</span>,
                    style: TextStyle(
                      color: Colors.deepPurple,
                    ),
                  ),
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}
</code></pre>
<p>This code is just a simple Login UI with two <code>textfields</code> and an elevated button. The <code>BlocConsumer</code> widget wraps the <code>Sign up</code> button and listens for changes in the <code>AuthenticationBloc</code> state. When a user presses the button, it dispatches an event to the <code>AuthenticationBloc</code> to initiate the user sign-up process.</p>
<p>Depending on the authentication state, this button may display different feedback or navigate to another screen. It checks for <code>AuthenticationSuccessState</code>, <code>AuthenticationLoadingState</code>, and <code>AuthenticationFailureState</code> states to respond accordingly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/ezgif.com-video-to-gif--1-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Img 2: A Login screen showing a login process with 2 out of the 3 states.</em></p>
<h3 id="heading-home-screen">Home Screen</h3>
<p>Create another file called <code>home_screen.dart</code> in the <code>screens</code> directory and add the code below to the file.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter_bloc/flutter_bloc.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../bloc/authentication_bloc.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> id = <span class="hljs-string">'home_screen'</span>;
  <span class="hljs-keyword">const</span> HomeScreen({<span class="hljs-keyword">super</span>.key});

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            <span class="hljs-keyword">const</span> Text(
              <span class="hljs-string">'Hello User'</span>,
              style: TextStyle(
                fontSize: <span class="hljs-number">20</span>,
              ),
            ),
            <span class="hljs-keyword">const</span> SizedBox(
              height: <span class="hljs-number">20</span>,
            ),
            BlocConsumer&lt;AuthenticationBloc, AuthenticationState&gt;(
              listener: (context, state) {
                <span class="hljs-keyword">if</span> (state <span class="hljs-keyword">is</span> AuthenticationLoadingState) {
                   <span class="hljs-keyword">const</span> CircularProgressIndicator();
                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (state <span class="hljs-keyword">is</span> AuthenticationFailureState){
                    showDialog(context: context, builder: (context){
                          <span class="hljs-keyword">return</span> <span class="hljs-keyword">const</span> AlertDialog(
                            content: Text(<span class="hljs-string">'error'</span>),
                          );
                        });
                }
              },
              builder: (context, state) {
                <span class="hljs-keyword">return</span> ElevatedButton(
                    onPressed: () {
                      BlocProvider.of&lt;AuthenticationBloc&gt;(context)
                      .add(SignOut());
                    }, child: <span class="hljs-keyword">const</span> Text(
                      <span class="hljs-string">'logOut'</span>
                      ));
              },
            ),
          ],
        ),
      ),
    );
  }
}
</code></pre>
<p>The code above represents the <code>HomeScreen</code> and it's also a simple page that consists of scaffold, a column, and a text widget but the interesting part is the <code>BlocConsumer</code> which is at the elevated button that says logOut. Let's look closely at that.</p>
<p>The <code>BlocConsumer</code> Listens to state changes from the <code>AuthenticationBloc</code>. It has two parameters - listener and builder.</p>
<ul>
<li><strong>listener</strong>: Listens to state changes and reacts based on the current state received from the <code>AuthenticationBloc</code>.</li>
<li>If the state is <code>AuthenticationLoadingState</code>, it shows a <code>CircularProgressIndicator</code>.</li>
<li>If the state is <code>AuthenticationFailureState</code>, it displays an <code>AlertDialog</code> with the message 'Error'.</li>
<li><strong>builder</strong>: Builds the UI based on the current state received from the <code>AuthenticationBloc</code>.</li>
<li>It renders an <code>ElevatedButton</code> labeled "Log Out".</li>
<li>When pressed, it triggers the <code>SignOut</code> event in the <code>AuthenticationBloc</code> via BlocProvider.</li>
</ul>
<p>With the Bloc authentication flow implemented, you can run your Flutter app and test the registration functionalities. Make sure to handle other authentication-related scenarios, such as user Login and password recovery, as required by your app's specifications. Also, you'll want to handle the errors gracefully to give the user a good experience.</p>
<p>If you want to clone the repo, you can check it out on GitHub <a target="_blank" href="https://github.com/emjaycodes/bloc_authentication_flow_article">here</a> and leave a like.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, we explored building a user authentication flow in Flutter using Firebase for authentication and the Bloc state management pattern for handling application state.</p>
<p>We learned how to set up Firebase in a Flutter project, create Blocs for authentication, and implement the authentication flow using Bloc.</p>
<p>By leveraging the power of Firebase and the predictability of Bloc, you can ensure a secure and seamless user authentication experience in your Flutter apps.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use URLs for State Management in React ]]>
                </title>
                <description>
                    <![CDATA[ For years, URLs have been synonymous with web navigation. But the tide is turning, especially with the emergence of single-page applications. In the React universe, URLs are stepping up to play a pivotal role in state management. This article will gu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-urls-for-state-management-in-react/</link>
                <guid isPermaLink="false">66bb890b7a6500a14ba5b769</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ url ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Fri, 06 Oct 2023 17:50:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/Article-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For years, URLs have been synonymous with web navigation. But the tide is turning, especially with the emergence of single-page applications. In the React universe, URLs are stepping up to play a pivotal role in state management.</p>
<p>This article will guide you through the transformative journey of URLs as state managers in the context of React applications. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Fundamentals of HTML and CSS</li>
<li>Fundamentals of ES6 JavaScript</li>
<li>Fundamentals of React, React Router and React Hooks.</li>
</ul>
<h2 id="heading-the-evolution-of-state-management-in-react">The Evolution of State Management in React</h2>
<p>Let's journey through the past:</p>
<ul>
<li><strong>setState</strong>: In the early days of React, many relied on component state, especially within <a target="_blank" href="https://react.dev/reference/react/Component#defining-a-class-component">class components</a>. It was straightforward to manage component-specific data. But it wasn't ideal for larger applications.</li>
<li><strong>Redux &amp; MobX</strong>: As applications grew in complexity, tools like <a target="_blank" href="https://redux.js.org/">Redux</a> and <a target="_blank" href="https://mobx.js.org/README.html">MobX</a> emerged. They centralized data management, making it easier to handle app-wide data.</li>
<li><strong>Context API &amp; Hooks</strong>: React's own <a target="_blank" href="https://react.dev/reference/react/useContext">Context API</a>, combined with the advent of hooks, brought about a more native way to manage the global state without adding extra libraries.</li>
</ul>
<h2 id="heading-managing-state-with-urls">Managing State with URLs</h2>
<p>At first, using a URL for managing state might seem unusual. But as you explore further, you'll discover several clear benefits:</p>
<ul>
<li><strong>Save Your Spot</strong>: By keeping state in the URL, your webpage remembers your place. So, if you bookmark a page, it will look the same when you come back to it later.</li>
<li><strong>Easy Sharing</strong>: If you're looking at something specific on a page, like a product or a chart, you can share the URL. Anyone who clicks it will see exactly what you’re seeing, making collaboration a breeze.</li>
<li><strong>Troubleshoot with Ease</strong>: Developers can find and fix issues faster because the URL shows the state of the app. They can see problems just by clicking on the shared link.</li>
</ul>
<p>In short, using URLs in this way helps keep your spot, share specific views, and makes problem-solving smoother for developers.</p>
<h2 id="heading-how-to-implement-url-based-state-management">How to Implement URL-based State Management</h2>
<p>Considering the size of this section, here’s everything you’ll learn.</p>
<ol>
<li>How to Set Up the Environment</li>
<li>Clearing the clutter</li>
<li>Project Breakdown / Analysis</li>
<li>Install the Necessary Dependencies</li>
<li>How to Fetch the Data and Design the UI</li>
<li>How to Store State in the URL</li>
<li>How to Read the State Stored in the URL</li>
<li>How to Customize the Product Page</li>
</ol>
<h3 id="heading-how-to-set-up-the-environment">How to Set Up the Environment</h3>
<p>Open your inbuilt terminal or code editor’s terminal (preferably) and run the following:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>This command uses <a target="_blank" href="https://vitejs.dev/guide/">Vite</a> (a lightweight tool that is used for building fast and optimized web applications) to scaffold a web app environment. Navigate down using your arrow keys and select React.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/02-Selecting-React.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting React from Vite Setup</em></p>
<p>Then select your preferred language combination – I’ll be using plain JS.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/03-Selecting-JS.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting Language in React</em></p>
<p>Next, move into your react folder using the cd “project-name” folder and run <code>npm install</code> to install all the project’s dependencies.</p>
<p>Finally, start the development server by running <code>npm run dev</code> and going to the respective URL (<a target="_blank" href="http://localhost:5173/">http://localhost:5173/</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/04-dev-server-running.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dev Server running</em></p>
<h3 id="heading-clearing-the-clutter">Clearing the clutter</h3>
<p>Make sure to clear the contents of all the CSS files and delete the <code>App.css</code> as you’ll need only 1 style file. Then, clear the contents of the <code>App</code> component and replace it with basic JSX content.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/05-clutter-cleared.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clutter Cleared in Dev Environment</em></p>
<p>This returns a clear page on your local server that looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/06-clear-server-page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clear Server page</em></p>
<h3 id="heading-project-breakdown-analysis">Project breakdown / analysis</h3>
<p>The project involves getting data from an API and persisting that data globally via the URL to be accessible across many components/pages.</p>
<p>A relatable example is when you’re on your favourite e-commerce site, you may see this cool gadget and want to share it with your friend.</p>
<p>You usually share the link from the browser to your friend’s social media DM which they can use to view the same product without any fuss by opening the link you sent to them.</p>
<p>Here’s a sneaky peek at the project we're going to build: 😉</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/1-sneaky-peek.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Sneaky peek of complete project</em></p>
<p>Intrigued?🌚 Let’s dive in then.</p>
<h3 id="heading-install-the-necessary-dependencies">Install the necessary dependencies</h3>
<p>Before you put anything on the page, you must first fully configure your development environment with the necessary dependencies.</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/json-server">json-server</a>: This package hosts your data on a local server, enabling you to fetch it like an external API.</li>
<li><a target="_blank" href="https://www.npmjs.com/package/react-router">react-router</a>: This package enables React to create SPAs that allow navigating without refreshing the page.</li>
</ul>
<pre><code class="lang-bash">npm i json-server react-router-dom
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/08-installing-dependencies-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Installing dependencies</em></p>
<ul>
<li>Then download the JSON data from this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/tree/main/data">GitHub(json-data)</a>, and the assets from this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/tree/main/public/assets">GitHub(assets-data)</a>.</li>
</ul>
<p>Now create a data folder in your root project directory and place the JSON file inside. Then create an assets folder in your public directory and place all images in that assets folder.</p>
<p>Your current folder structure should be like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/07-folder-structure-after-downloading-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder structure after downloading files</em></p>
<p>Next, modify your package.json file by adding a script which starts up the json-server</p>
<pre><code class="lang-json"><span class="hljs-string">"server"</span>: <span class="hljs-string">"json-server --watch data/products.json --port 9000 "</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/09-adding-a-server-script.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding server script to package.json</em></p>
<p>After that, open your terminal and start up the server with <code>npm run server</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/10-starting-data-server.png" alt="Image" width="600" height="400" loading="lazy">
<em>Starting data server</em></p>
<p>With this, your server is running and the content of your JSON file can be accessed through the URL provided.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/11-data-on-browser.png" alt="Image" width="600" height="400" loading="lazy">
<em>Data on Browser</em></p>
<p>Ps: If you want to view JSON files in the browser like I do, download the browser extension – <a target="_blank" href="https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh">JSON Viewer</a>.</p>
<h3 id="heading-how-to-fetch-the-data-and-design-the-ui">How to fetch the data and design the UI</h3>
<p>Start by creating a HomePage component and importing it into the App component. This component will contain all the data in the first screen you saw earlier.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/12-importing-the-homepage.png" alt="Image" width="600" height="400" loading="lazy">
<em>Importing the Homepage</em></p>
<p>In the <code>HomePage</code> component, use a <code>useEffect</code> hook to fetch all the data from your local API.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{

      <span class="hljs-keyword">try</span>{
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);
      <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
      <span class="hljs-built_in">console</span>.log(clothesData);   
      }
      <span class="hljs-keyword">catch</span> (error) {  <span class="hljs-built_in">console</span>.log(error);}
      }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>At the moment, you can already view the data fetched in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/13-evidence-of-fetching-data.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evidence of data fetching</em></p>
<p>Next, store your data in a state using the <code>useState</code> hook and populate your interface with that data.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([]);

  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);
        <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-built_in">console</span>.log(clothesData);
        <span class="hljs-comment">//Storing happens here</span>
        setProducts(clothesData);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      }
    }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"products__list"</span>&gt;</span>
        {products.map((product) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>
                      <span class="hljs-attr">className</span>=<span class="hljs-string">"product__item"</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{product.imageUrl}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{product.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>All the styling required in this project is in this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/blob/main/src/index.css">CSS file</a>. Alternatively, you can paste these stylings in your index.css, which gives the same result.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&amp;display=swap"</span>);

*,
<span class="hljs-selector-pseudo">::before</span>,
<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}
<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">62.5%</span>;
}
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Nunito"</span>, sans-serif;
}

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;

  &amp; span {
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">3rem</span>;
  }
}

<span class="hljs-selector-tag">a</span>,
<span class="hljs-selector-tag">h3</span> {
  <span class="hljs-attribute">text-decoration</span>: none;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#a04000</span>;
}

<span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;
}

<span class="hljs-selector-class">.homepage</span> {
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">3rem</span>;

  &amp; &gt; * {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  }
}

<span class="hljs-selector-class">.products__list</span> {
  <span class="hljs-attribute">column-count</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">column-gap</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;

  &amp; &gt; * {
    <span class="hljs-attribute">break-inside</span>: avoid;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">2rem</span>;
  }

  &amp; <span class="hljs-selector-class">.product__item</span> {
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">position</span>: relative;
    <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;

    &amp; h2 {
      <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;
      <span class="hljs-attribute">bottom</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">left</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
      <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">z-index</span>: <span class="hljs-number">2</span>;
      <span class="hljs-attribute">position</span>: absolute;
      <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">img</span> {
      <span class="hljs-attribute">scale</span>: <span class="hljs-number">1.1</span>;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">h2</span> {
      <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">10px</span>, -<span class="hljs-number">10px</span>);
    }
  }
}

<span class="hljs-selector-class">.single__product</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">4rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">overflow</span>: hidden;

  &amp; section {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">flex-direction</span>: column;

    &amp; figure {
      <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
      <span class="hljs-attribute">overflow</span>: hidden;

      &amp; .product__img {
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
      }
    }

    &amp; <span class="hljs-selector-tag">aside</span> {
      <span class="hljs-attribute">display</span>: flex;
      <span class="hljs-attribute">flex-direction</span>: column;
      <span class="hljs-attribute">justify-content</span>: flex-end;
      <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5rem</span>;

      &amp; &gt; h2 {
        <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5rem</span>;
      }
      &amp; &gt; <span class="hljs-selector-tag">h3</span> {
        <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.6rem</span>;
      }
      &amp; <span class="hljs-selector-tag">span</span> {
        <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">160</span>, <span class="hljs-number">64</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
        <span class="hljs-attribute">padding-inline</span>: <span class="hljs-number">1rem</span>;
        <span class="hljs-attribute">align-self</span>: flex-start;
      }
    }
  }
}

<span class="hljs-comment">/* Small devices (portrait tablets and large phones, 600px and up) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">600px</span>) {
  <span class="hljs-selector-class">.products__list</span> {
    <span class="hljs-attribute">column-count</span>: <span class="hljs-number">2</span>;
  }

  <span class="hljs-selector-class">.single__product</span> {
    &amp; section {
      <span class="hljs-attribute">flex-direction</span>: row;

      &amp; .product__img {
        <span class="hljs-attribute">max-width</span>: <span class="hljs-number">300px</span>;
      }
    }
  }
}

<span class="hljs-comment">/* Medium devices (landscape tablets, 768px and up) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-class">.homepage</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">4rem</span>;
  }
  <span class="hljs-selector-class">.products__list</span> {
    <span class="hljs-attribute">column-count</span>: <span class="hljs-number">3</span>;
  }
}
</code></pre>
<p>At the moment, your home page should already look identical to the demo version.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/14-page-with-styings-applied.png" alt="Image" width="600" height="400" loading="lazy">
<em>Home page with styles added</em></p>
<h3 id="heading-how-to-store-state-in-the-url">How to store state in the URL</h3>
<p>In order to manage and share state across multiple pages using the URL, you first need to define routes using the react-router package.</p>
<p>Start by creating a route for the homepage:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { BrowserRouter, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> HomePage <span class="hljs-keyword">from</span> <span class="hljs-string">"./HomePage"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<ul>
<li>The <strong>BrowserRouter</strong> component wraps your entire application or the part of your app where you want to use routing.</li>
<li>The <strong>Routes</strong> component wraps all your <strong>Route</strong> components and is responsible for rendering the first route that matches the current location. </li>
<li>The <strong>Route</strong> component represents a single route in your application.</li>
</ul>
<p>Next, create a <code>ProductItem</code> component responsible for showing a single item and its equivalent route.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { BrowserRouter, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> HomePage <span class="hljs-keyword">from</span> <span class="hljs-string">"./Homepage"</span>;
<span class="hljs-keyword">import</span> ProductItem <span class="hljs-keyword">from</span> <span class="hljs-string">"./ProductItem"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
         <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"product"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">ProductItem</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<p>To view the <code>ProductItem</code> component, head over to your <code>HomePage</code> and wrap each individual product with a <code>Link</code> element pointing to the product page with their unique ID.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([]);

  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);

      <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
      <span class="hljs-built_in">console</span>.log(clothesData);
      setProducts(clothesData);
    }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"products__list"</span>&gt;</span>
        {products.map((product) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>
           // <span class="hljs-attr">Moving</span> <span class="hljs-attr">to</span> <span class="hljs-attr">the</span> <span class="hljs-attr">product</span> <span class="hljs-attr">page</span>
           <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`/<span class="hljs-attr">product</span>?<span class="hljs-attr">id</span>=<span class="hljs-string">${product.id}</span>`}
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__item"</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{product.imageUrl}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{product.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>Clicking on any product now routes you to the product page and shows the <code>ProductItem</code> component.</p>
<p>On closer observation, you may notice that the id of each item is appended to the URL via its id property (for example: product?id=12345678).  This implies that you have successfully stored the id state to the URL.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/02-confirming-id-state-shared.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-read-the-state-stored-in-the-url">How to read the state stored in the URL</h3>
<p>In order to show data for each product, you have to read the state stored in the URL.</p>
<p>To implement this, start by creating a new custom hook (this helps for reusability). In your custom hook, import the <code>useSearchParams</code> hook.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useSearchParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useURLID</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [searchParams] = useSearchParams();
}
</code></pre>
<p>The <code>useSearchParams</code> hook allows you to interact with the query parameters of the URL (part of the URL that comes after the ? as seen in your URL earlier).</p>
<p>In order to retrieve the values from the URL, use the <code>get</code> method and pass in the name of the value you want to retrieve, in this case, the <code>id</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useSearchParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useURLID</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [searchParams] = useSearchParams();
  <span class="hljs-keyword">const</span> id = searchParams.get(<span class="hljs-string">"id"</span>);
  <span class="hljs-keyword">return</span> { id };
}
</code></pre>
<p>To test out your hook, import it into the <code>ProductItem</code> page and extract the values.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Product Item {id}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/2-confirming-id-state-shared.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And voilà! Your id state is now global and can used by any component in your app. Bravo!</p>
<h3 id="heading-how-to-customize-the-product-page">How to customize the Product Page</h3>
<p>In order to fully achieve what was shown in the demo, perform another fetch based on the id to get the data for that product.</p>
<p>Start by creating states to store the data and account for the data loading.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
<span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Then use a <code>useEffect</code> hook to fetch and store the data based on the unique product id.</p>
<pre><code class="lang-js">  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:9000/products/<span class="hljs-subst">${id}</span>`</span>);

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);
</code></pre>
<p>Next, use the data received to populate the interface.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:8000/products/<span class="hljs-subst">${id}</span>`</span>);

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);



  <span class="hljs-comment">// If loading, display the loading div</span>
  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-comment">// If not loading, display the product details</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"single__product"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
               <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
          {singleProduct.itemName} Page id: {id}
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img"</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{singleProduct.imageUrl}</span>
            <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">aside</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{singleProduct.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{singleProduct.notes}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>
            Category: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{singleProduct.type}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Width: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.width}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Length: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.length}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">aside</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Finally, account for easy navigation by providing a back button to go to the home page. You can do this using the <code>useNavigate</code> hook in react-router. This hook provides a function that allows you to programmatically navigate to other parts of your application. </p>
<p>Simply import the <code>useNavigate</code> hook, and initialize it with a variable like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">const</span> navigate = useNavigate();
</code></pre>
<p>Then call this function with an event handler, and pass in the home page route.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:9000/products/<span class="hljs-subst">${id}</span>`</span>);

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);

  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-comment">// If loading, display the loading div</span>
  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-comment">// If not loading, display the product details</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"single__product"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
       // Navigate to the home page
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate("/")}&gt;🔙 <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
          {singleProduct.itemName} Page id: {id}
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img"</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{singleProduct.imageUrl}</span>
            <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">aside</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{singleProduct.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{singleProduct.notes}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>
            Category: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{singleProduct.type}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Width: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.width}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Length: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.length}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">aside</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Testing your final result now gives the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/final-take-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Final take showing all features</em></p>
<h2 id="heading-real-world-examples">Real-World Examples</h2>
<ul>
<li><strong>E-commerce platforms</strong>: Think of sites like Amazon. They use URLs to let you share specific product searches or settings. Thanks to this, people can easily share their favourite items or shopping lists with friends.</li>
<li><strong>Data Tools</strong>: Tools like <a target="_blank" href="https://www.tableau.com/">Tableau</a> save your custom views in the URL. This means teams can share specific data pictures with each other, making talks, shows, and decisions faster and clearer.</li>
</ul>
<h3 id="heading-additional-information">Additional Information</h3>
<p>I’d like to point out a couple of things in the article not highlighted.</p>
<ul>
<li>The CSS used contains <a target="_blank" href="https://developer.chrome.com/articles/css-nesting/">native CSS nesting</a> that isn’t fully supported by all browsers, so if there are UI irregularities you notice, it may be from the browser you’re using. Feel free to switch to a browser like Google Chrome for better support or check for browser support with a tool like <a target="_blank" href="https://caniuse.com/">CanIUse</a> and add polyfills to your code.</li>
<li>If this article delved into things that were a tad complicated for you (how routing works), feel free to check out this article on <a target="_blank" href="https://www.freecodecamp.org/news/improve-user-experience-in-react-by-animating-routes-using-framer-motion/">Routing Animations</a> for a better understanding.</li>
<li>If you’re interested in the full code, here’s the repo, <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management">GitHub</a>, and the Live version is here. <a target="_blank" href="https://free-code-camp-url-state-manangement.netlify.app/">Demo</a></li>
<li>As an added feature, I made the code fully responsive for anyone interested in creating masonry grids for future projects, cheers!🍷</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>React's state management has evolved, with URL-based state emerging as a standout. This method not only simplifies state management but also fosters collaboration and transparency between users and developers.</p>
<p>So, the next time you're online and think of sharing data via a URL, remember that you have the tools to implement this feature yourself 😉. It's a nudge for developers to explore the untapped potential of URLs in state management.</p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: <a target="_blank" href="mailto:Jajadavidjid@gmail.com">Jajadavidjid@gmail.com</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Stateful vs Stateless Architecture – Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ In programming, "state" refers to the condition of a system, component, or application at a particular point in time. As a simple example, if you are shopping on amazon.com, whether you are currently logged into the site or if you have anything store... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/stateful-vs-stateless-architectures-explained/</link>
                <guid isPermaLink="false">66d45e1d680e33282da25e61</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Adetunji ]]>
                </dc:creator>
                <pubDate>Mon, 21 Aug 2023 21:08:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/cover-photo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In programming, "state" refers to the condition of a system, component, or application at a particular point in time.</p>
<p>As a simple example, if you are shopping on amazon.com, whether you are currently logged into the site or if you have anything stored in your cart are some examples of state.</p>
<p>State represents the data that is stored and used to keep track of the current status of the application. Understanding and managing state is crucial for building interactive and dynamic web applications.</p>
<p>The concept of a “state” crosses many boundaries in architecture. Design patterns (like REST and GraphQL), protocols (like HTTP and TCP), firewalls and functions can be stateful or stateless. But the underlying principle of “state” cutting across all of these domains remains the same.</p>
<p>This article will explain what state means. It will also explain stateful and stateless architectures with some analogies and the benefits and tradeoffs of both.</p>
<h2 id="heading-what-is-stateful-architecture">What is Stateful Architecture?</h2>
<p>Imagine you go to a pizza restaurant to eat some food. In this restaurant, there is only a single waiter, and the waiter takes detailed notes on your table number, what you ordered, your preferences based on past orders, like what type of pizza crust you like or toppings you are allergic to, and so on.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3d2bd50-8945-4fb4-b36a-1d4730beebe5_1726x1080.png" alt="Image" width="1456" height="911" loading="lazy"></p>
<p><em>Illustration of a waiter taking a person's order at a pizza restaurant</em></p>
<p>All of these pieces of information that the waiter writes down in their notepad are the customer's state. Only the waiter serving you has access to this information. If you want to make a change to your order or check how its coming along, you need to speak to the same waiter that took your order. But since there is only one waiter, that is not a problem.</p>
<p>Now, suppose the restaurant starts to get busier. Your waiter has to respond to other guests so more waiters are called to work. You now want to check the status of your order and make a small change to it – a plain crust instead of a cheesy crust. The only available waiter is different from the one who initially took your order.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b483849-6dc8-4a90-a491-199150d71547_1566x1020.png" alt="Image" width="1456" height="948" loading="lazy"></p>
<p><em>Illustration showing a different waiter being unable to help the customer change their order</em></p>
<p>This new waiter does not have details of your order, that is your state. Naturally, they will not be able to check the status of your order or make changes to it. A restaurant that operates like this, where only the waiter that initially took your order can give you updates about it, or make changes to it, follows a stateful design.</p>
<p>Similarly, a stateful application will have a server that remembers clients' data (that is, their state). All future requests will be routed to the same server using a load balancer with sticky sessions enabled. In this way, the server is always aware of the client.</p>
<p>The diagram below shows two different users trying to access a web server through a load balancer. Since the application state is maintained on the servers, the users must always be routed to the same server for every single request in order to preserve state.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd494a45c-284b-4dd8-a6f1-5eb072157c70_1028x834.png" alt="Image" width="1028" height="834" loading="lazy"></p>
<p><em>Diagram showing how a stateful application works</em></p>
<p>Sticky sessions is a configuration that allows the load balancer to route a user's requests consistently to the same backend server for the duration of their session. This is in contrast to <a target="_blank" href="https://lightcloud.substack.com/i/102200211/load-balancing-explained">traditional load balancing</a>, where requests from a user can be directed to any available backend server in a round-robin or other load distribution pattern.</p>
<p>What is the problem with a stateful architecture? Imagine a restaurant run in this manner. While it may be ideal and easy to implement for a small, family run restaurant with only a few customers, such a design is <strong>not fault tolerant</strong> and <strong>not scalable</strong>.</p>
<p>What happens if the waiter who took a customer's order has an emergency and needs to leave? All the information regarding that order leaves with that waiter as well. This disrupts the customer’s experience, since any new waiter brought in to replace the old one has no knowledge of previous orders. This is a design that is not fault tolerant.</p>
<p>Also, having to distribute requests so that the same customer can only speak to the same waiter means that the load on different waiters is not equally distributed. Some waiters will be overwhelmed with requests if you have a very demanding customer who always modifies or adds things to their order. Some of the other waiters will have nothing to do, and can’t step in to help. Again, this is a non scalable design.</p>
<p>Similarly, storing state data for different customers on different servers is not fault tolerant and not scalable. A server failure will lead to loss of state data. So, if a user is logged in and about to checkout for a large order on Amazon.com for example, the user will be forced to re-authenticate and the user's basket will be empty. They would have to log in again and fill up their basket from scratch – a poor user experience.</p>
<p>Scalability will also be difficult to achieve during peak times like Black Friday with a stateful design. New servers will be added to the <a target="_blank" href="https://lightcloud.substack.com/i/102200211/auto-scaling-explained">auto scaling group</a> but since sticky sessions are enabled, clients will be routed to the same server, causing them to be overwhelmed, which can cause an increase in response times - a poor user experience.</p>
<p>Stateless architectures solve a lot of these problems.</p>
<h2 id="heading-what-is-stateless-architecture">What is Stateless Architecture?</h2>
<p>“Stateless” architecture is a confusing term, as it implies the system is without state. A stateless architecture does not, however, mean that state information is not stored. It simply means that state information is stored outside of the server. Therefore, the state of being stateless only applies to the server.</p>
<p>Bringing back the restaurant analogy, waiters in a stateless restaurant can be thought of as having perfectly forgetful memories. They do not recognise old customers, and can’t recall what you ordered or how you like your pizza. They will simply take note of customers' orders on a separate system, say a computer, that is accessible by all the waiters. They can then revert back to the computer to get details of an order and make changes to it as required.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bc5ab03-b96a-4e4b-b27e-ad9077a4bdc3_1852x932.png" alt="Image" width="1456" height="733" loading="lazy"></p>
<p><em>Illustration of a "forgetful" waiter taking an order and then consulting the computer about orders</em></p>
<p>By storing the ‘state’ of a customer's order on a central system accessible by other waiters, any waiter can serve any customer.</p>
<p>In a stateless architecture, HTTP requests from a client can be sent to any of the servers.</p>
<p>State is typically stored on a separate database, accessible by all the servers. This creates a fault tolerant and scalable architecture since web servers can be added or removed as needed, without impacting state data.</p>
<p>The load will also be equally distributed across all servers, since the load balancer will not need a sticky session configuration to route the same clients to the same servers.</p>
<p>The diagram below shows two different users trying to access a web server through a load balancer. Since the application state is maintained separately from the servers, the users can be routed to any of the servers, which will then get the state information from an external database accessible by both servers.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360b7c09-6e3c-4443-a05b-b58f70dc0039_1322x804.png" alt="Image" width="1322" height="804" loading="lazy"></p>
<p><em>Illustration showing a diagram of stateless architecture</em></p>
<p>Typically, state data is stored in a cache like <a target="_blank" href="https://redis.io/">Redis</a>, an in-memory data store. Storing state data in-memory improves read and write times, compared to storing it on disk, as explained <a target="_blank" href="https://lightcloud.substack.com/i/81969975/compute-memory-and-storage-an-analogy">here</a>.</p>
<h2 id="heading-bringing-it-together">Bringing it Together</h2>
<p>This article has described how stateful and stateless web applications work and the trade-offs of both. But the principle of statefulness and statelessness apply beyond web applications.</p>
<p>If we look at network protocols as an example, HTTP is a stateless protocol. This means that each HTTP request from a client to a server is <strong>independent</strong> and carries <strong>no knowledge of previous requests</strong> or their context. The server treats each request as a separate and isolated transaction, and it doesn't inherently maintain information about the state of the client between requests.</p>
<p>State is either maintained on the servers (stateful architecture) or in a separate database outside the servers (stateless architecture). The HTTP protocol itself does not maintain state.</p>
<p>Unlike the stateless nature of HTTP, <a target="_blank" href="https://www.freecodecamp.org/news/tcp-vs-udp/">the TCP protocol</a> is connection-oriented and stateful. It establishes a connection between two devices (usually a client and a server) and maintains a continuous communication channel until the connection is terminated.</p>
<p>The same logic applies to firewalls as well, which can be stateful or stateless.</p>
<p>In AWS, a security group is a virtual firewall that controls inbound and outbound traffic for virtual machines or instances within a cloud environment. Security groups are stateful. When you allow a specific incoming traffic flow, the corresponding outgoing traffic flow is automatically allowed as well. In other words, the state of the connection is tracked.</p>
<p>Network Access Control Lists (NACLs) are used to control inbound and outbound traffic at the subnet level in AWS. NACLs are stateless. Being stateless means that you must explicitly define rules for both incoming and outgoing traffic.</p>
<p>Unlike security groups, where response traffic is automatically allowed when you allow incoming traffic, NACLs require you to define separate rules for inbound and outbound traffic.</p>
<p>Functions and design patterns can also be stateful or stateless.</p>
<p>The key principle behind something that is stateful is that it has perfect memory or knowledge of previous calls or requests, while something that is stateless has no memory or knowledge of previous calls or requests.</p>
<p>Hopefully you now have a good grasp of how stateful and stateless applications work and can decide which option is best for your applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Manage State in Your Applications – useState() vs Redux ]]>
                </title>
                <description>
                    <![CDATA[ State management is crucial for handling an application's data, how users interact with it, and how different parts of the app behave.  And it's not something you'll use only in React.js, but also in other popular tools like Angular.js, Vue.js, and N... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/usestate-vs-redux-state-management/</link>
                <guid isPermaLink="false">66b9f48468badebf96ed5f9a</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Mon, 31 Jul 2023 21:35:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/cover-react-redux.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is crucial for handling an application's data, how users interact with it, and how different parts of the app behave. </p>
<p>And it's not something you'll use only in <a target="_blank" href="https://react.dev/">React.js</a>, but also in other popular tools like <a target="_blank" href="https://angularjs.org/">Angular.js,</a> <a target="_blank" href="https://vuejs.org/">Vue.js,</a> and <a target="_blank" href="https://nextjs.org/">Next.j</a>s.</p>
<p>There are two common ways to manage a state: useState and Redux.  But there are also other options like <a target="_blank" href="https://mobx.js.org/README.html">MobX</a>, <a target="_blank" href="https://www.npmjs.com/package/zustand">Zustand</a>, and <a target="_blank" href="https://recoiljs.org/">Recoil</a>.</p>
<p>In this article, we'll learn about state management and why it's important. We'll also explore common state management methods and understand how they work.</p>
<p> After reading this article, you'll be able to pick the best state management method for your app.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Have an understanding of React.</li>
<li>Make sure you install <a target="_blank" href="https://nodejs.org/en">Node.js</a> on your system.</li>
</ul>
<h2 id="heading-what-is-state-management-and-why-is-it-important">What is State Management and Why Is It Important?</h2>
<p>State management is a crucial part of application development. It lets programmers control how the app responds to different events and user actions. </p>
<p>It helps you create dynamic and interactive interfaces, making the user experience better.</p>
<h3 id="heading-what-sort-of-sitesapps-use-state-management">What Sort of Sites/Apps Use State Management?</h3>
<p>State management is used in lots of websites and apps, from simple to complex ones. </p>
<p>React and frameworks like Angular.js, Vue.js, and Next.js often use state management to handle data and control how components behave.</p>
<h3 id="heading-what-to-consider-when-choosing-a-state-management-strategy">What to Consider When Choosing a State Management Strategy</h3>
<ol>
<li><strong>The application's complexity</strong>: For simple apps with few components, use <code>useState()</code>. For complex apps with extensive state interactions, choose <code>Redux</code>.</li>
<li><strong>Team size and skill level:</strong> <code>useState()</code> is okay for smaller teams or developers new to state management because it's easy to understand. <code>Redux</code> can be good for larger teams with experienced developers.</li>
<li><strong>Sharing State:</strong> <code>Redux</code> centralized state management is easier to use in some cases than <code>useState()</code>.</li>
<li><strong>Scalability:</strong> <code>Redux</code>  offers advanced features that help manage complex states.</li>
</ol>
<h2 id="heading-state-management-examplesusestate-vs-redux">State Management Examples:<code>useState()</code> vs <code>Redux</code></h2>
<p>To understand state management better, let's check out a practical example that shows how <code>useState()</code> and <code>Redux</code> work in React.</p>
<h3 id="heading-setting-up-the-project">Setting Up the Project</h3>
<p>First, go to the project folder. Create a React boilerplate using the create-react-app command or the Vite tool.</p>
<p>I prefer <strong><a target="_blank" href="https://vitejs.dev/">vite</a></strong> (and this is what the React document currently recommends), because it's faster for development and easier to configure. Vite is also more versatile and supports other front-end frameworks such as Svelte. But if you prefer, create-react-app is still an option.</p>
<p>Next, in the terminal of your editor, type this command:</p>
<pre><code class="lang-javascript">npx create-react-app ./ or npx create-vite@latest ./
</code></pre>
<p><code>./</code> creates the React boilerplate for you right inside the created folder or directory.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Code_Vp1nLXqZqd.gif" alt="Creating the react boilerplate (template) " width="600" height="400" loading="lazy">
<em>Creating the react boilerplate (template)</em></p>
<h3 id="heading-option-1-managing-state-with-usestate">Option 1: Managing State with <code>useState()</code></h3>
<p><code>useState()</code> is a built-in hook in React. It manages the state of React applications <strong>locally.</strong> </p>
<p><code>useState()</code> introduces state management capabilities in functional components. This means you can now use stateful logic within functional components.</p>
<p>In React, you have access to various other hooks that you can import and use in your applications. These hooks make your app more dynamic and efficient.</p>
<p>Check out this article to learn more: <a target="_blank" href="https://ijaycent.hashnode.dev/simplify-your-react-programming-effortlessly-with-these-8-amazing-hooks">Simplify your React programming effortlessly with these 8 amazing hooks</a>.</p>
<p>For more information on the <code>useState()</code> hook, <a target="_blank" href="https://www.freecodecamp.org/news/usestate-hook-3-different-examples/">you can check out this tutorial</a>. It will provide you with detailed insights and examples related to <code>useState()</code> in React.</p>
<h3 id="heading-pros-of-using-the-usestate-hook-in-a-react-application">Pros of Using the <code>useState()</code> Hook in a React Application</h3>
<ol>
<li><code>useState()</code> has a smaller footprint than external state management libraries like <code>Redux</code>. This reduces the application's bundle size and improves performance.</li>
<li>It allows for more clear and intuitive state management within functional components.</li>
</ol>
<h3 id="heading-cons-of-using-the-usestate-hook-in-a-react-application">Cons of Using the <code>useState()</code> Hook in a React Application</h3>
<ol>
<li>It is cumbersome to manage the state of complex components with many variables.</li>
<li>Due to its limited capabilities, it leads to issues like prop drilling, which can be a bit confusing if not understood.</li>
<li>It triggers a re-render of the component impacting performance.</li>
</ol>
<h3 id="heading-how-to-use-usestate-in-react-applications">How to Use  <code>useState()</code> in React Applications</h3>
<p>So let's create an application that changes the color based on the user's input.</p>
<p>Using <code>useState()</code> involves a simple process:</p>
<ul>
<li>Import the <code>useState()</code> hook from the 'react' library.</li>
<li>Define a state variable and its initial value using array destructuring.</li>
<li>Then, define another state variable that takes in the color choice of the user when typed.</li>
<li>Use the state variable and its corresponding setter function within the component's logic to read or update the state.</li>
</ul>
<p>Here's what that looks like in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> State = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [text, setText] = useState(<span class="hljs-string">'black'</span>);
  <span class="hljs-keyword">const</span> [color, setColor] = useState(<span class="hljs-string">'black'</span>); <span class="hljs-comment">// Another state to store the chosen color by the user</span>

  <span class="hljs-keyword">const</span> handleInputChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setText(e.target.value);
  };

  <span class="hljs-comment">// A function is been declared</span>
  <span class="hljs-keyword">const</span> handleButtonClick = <span class="hljs-function">() =&gt;</span> {
    setColor(text); <span class="hljs-comment">// it updates the chosen color when the button is clicked</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> <span class="hljs-attr">color</span> }}&gt;</span>
        Progressively effective resources via business metrics.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'inputBtn-container'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">'input'</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{text}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleButtonClick}</span>&gt;</span>
          Change text color
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> State;
</code></pre>
<p>In the above code, the state variable <code>text</code> is set to the initial state (color) using <code>useState()</code>. The <code>setText</code> function is set to update the value of color when the button is clicked.</p>
<p>The second state defined is to store the color update from the user. So the <code>text</code> color remains unchanged until the button is clicked. Once the button is clicked, the color state updates with <code>text</code> value, changing <code>text</code> color to what the user types.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/chrome_bJlWaFiHPQ.gif" alt="modified state of a application using useState()" width="600" height="400" loading="lazy">
<em>Result</em></p>
<h3 id="heading-option-2-managing-state-with-redux">Option 2: Managing State with <code>Redux</code></h3>
<p><code>Redux</code> is a JavaScript library for managing states in applications. It works with React and other frameworks. </p>
<p><code>Redux</code> helps you manage the <strong>global</strong> state of your app. It improves your app's performance as well.</p>
<p>Think of <code>Redux</code> as a traffic controller for the data in the app. It makes sure that the right information goes to the right places, so everything runs smoothly.</p>
<h3 id="heading-pros-of-using-redux-in-your-application">Pros of Using <code>Redux</code> in Your Application</h3>
<p><code>Redux</code> might seem complex at first, but it comes with several advantages that make learning it worthwhile:</p>
<ol>
<li><code>Redux</code> can be used with other front-ends frameworks not only in React applications (for example Angular.js, Vue.js, and Next.js).</li>
<li><code>Redux</code> allows you to store all the states in a central store, instead of scattering states across many components. This makes it easier to understand, track, and manage the application state.</li>
<li>Many large companies use <code>Redux</code> to manage the state of their application.</li>
</ol>
<h3 id="heading-cons-of-using-redux-in-your-application">Cons of Using <code>Redux</code> in Your Application</h3>
<ol>
<li>Using <code>Redux</code> can make your app more complicated, especially if you're new to it. You'll need to learn new concepts and write more code, which might take time to understand and use.</li>
<li><code>Redux</code> needs more code compared to <code>useState()</code>.</li>
<li>If your app is small or doesn't have complex state needs, using <code>Redux</code> may be unnecessary.</li>
<li>Debugging can be challenging in a complex Redux setup.</li>
</ol>
<h3 id="heading-how-to-use-redux-in-your-application">How to Use <code>Redux</code> in Your Application:</h3>
<p>First, you'll need to install the Redux package:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Code_jSqM9Qi2Oc.gif" alt="how redux is been installed in your terminal " width="600" height="400" loading="lazy">
<em>Installing redux into your Code editor</em></p>
<p>The gif above shows that I ran three commands together in the terminal. This is a personal preference. </p>
<p><strong>What are these commands doing:</strong></p>
<ul>
<li><code>npm install redux</code> installs the <code>Redux</code> library.</li>
<li><code>react-redux</code> signifies that <code>Redux</code> is being used in a React application. It provides integration.</li>
<li><code>@reduxjs/toolkit</code> simplifies <code>Redux</code>, especially for beginners. It offers helpful tools and abstractions that make working with Redux easier and less complex for new developers.</li>
</ul>
<p>Next, check to make sure that <code>Redux</code> has been added to your dependencies. Look at your <code>package.json</code> file. It contains important information about the packages used in your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/redux-depency2.png" alt="react-dependencies" width="600" height="400" loading="lazy">
<em>react-dependencies</em></p>
<p>Then import {configureStore} from <code>@reduxjs/toolkit</code> to the <code>main.js</code> or <code>index.js</code>.</p>
<p>Use the provider tag to wrap up the main component of our app. Provide the <code>store</code> as an attribute (props) to the provider. This makes the store accessible globally throughout our application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-136.png" alt="import of the store and provider at main.js or index.js file" width="600" height="400" loading="lazy">
<em>import of the store and provider tag</em></p>
<p>Let's go over some key terms used in <code>Redux</code>:</p>
<p><strong>Store</strong>: A "container" in our application is like a storage unit. Inside the store, we will define the <strong>reducer</strong>. </p>
<p><code>Redux</code> operates based on the principles of a centralized store. It  acts as a central store that holds the application's entire state. When any component needs access to the state or needs to be updated , it interacts with the store. The store then manages the data and propagates changes to the relevant parts of the application.</p>
<p><strong>Reducer</strong>: A reducer is an object that takes two inputs: the previous state and an action. It returns the updated state based on the dispatched actions. It examines the activity and decides how to update the app's state. </p>
<p>Reducers in Redux control how our app reacts to user input. This flexibility makes it easy to maintain and change our code when needed. We can use the store and Provider imports to update our application.</p>
<h3 id="heading-redux-example"><code>Redux</code> Example</h3>
<p>So let's create an application that changes the colour based on the user's input and use Redux to manage state this time.</p>
<p>First, make a folder called <code>components</code>. Inside that folder, create a file named <code>ChangeColor.jsx</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-137.png" alt="Initial state" width="600" height="400" loading="lazy">
<em>Initial state of the application</em></p>
<p>Here's the output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/static-redux.png" alt="output" width="600" height="400" loading="lazy">
<em>static output</em></p>
<p>In your project directory, create a folder named <code>features</code>. Inside this folder, create a file called <code>Color.js</code> to hold the Redux logic for your application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/color-redux.png" alt="Color.js" width="600" height="400" loading="lazy">
<em>color.js</em></p>
<p>Next, we want to enable users to input their desired color. To do that, import the useState() hook like this:</p>
<p><strong><code>ChangeColor.jsx</code></strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;   <span class="hljs-comment">// useState() hook</span>

<span class="hljs-keyword">const</span> ChangeColor = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [color, setColor] = useState(<span class="hljs-string">''</span>); 
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Progressively effective resources via business metrics.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'inputBtn-container'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">'input'</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span>&gt;</span>change color text<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChangeColor;
</code></pre>
<p>At the <code>color.js</code>. This file holds the Redux logic for your application.</p>
<pre><code class="lang-js">
<span class="hljs-comment">// Import necessary functions from Redux Toolkit</span>
<span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;<span class="hljs-comment">// Creating a slice for functionality is essential.</span>

<span class="hljs-comment">// Define the initial state for the slice</span>
<span class="hljs-keyword">const</span> initialState = <span class="hljs-string">"black"</span>


<span class="hljs-comment">// Create a slice using the createSlice function</span>
<span class="hljs-keyword">const</span> themeSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'theme'</span>, <span class="hljs-comment">// Name of the slice</span>
  <span class="hljs-attr">initialState</span>: { <span class="hljs-attr">value</span>: initialState},<span class="hljs-comment">// Initial state for the slice</span>
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">changeColor</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>)=&gt;</span>{
      state.value=action.payload <span class="hljs-comment">// Update the color value based on the dispatched action</span>
    },
    }
  }
})
</code></pre>
<p>Let's see what's going on in this code:</p>
<ul>
<li><code>createSlice</code> is a function from the Redux Toolkit that lets developers create reducers in a clear and organized way. It simplifies splitting logic and accessing it across the application. With createSlice, changing values and understanding the code become easier.</li>
<li><code>name</code> is a string that defines the name of the slice. This name is used as a prefix for the generated action type strings.</li>
<li><code>initialState</code> is the initial state value for the slice.</li>
<li><code>reducers</code> are objects that take two inputs – the previous state and an action. The reducer returns the updated state based on the dispatched actions. It examines the activity and decides how to update the app's state. Reducers in Redux control how our app reacts to user input. This flexibility makes it easy to maintain and change our code when needed. We can use the store and Provider imports to update our application. Using the reducer, we can manage and update the application in a structured way. It helps us track changes according to our desired logic.</li>
<li><code>state</code> refers to the data stored and managed by the application. It holds the current values of variables, properties, or fields that determine how the application behaves and looks.</li>
<li><code>action</code> is a plain JavaScript object that describes an intention to change the state. It's how we communicate with the reducers to initiate state updates.</li>
</ul>
<p>After defining the reducer logic, we can make it reusable by exporting it from the file and importing it wherever we need to manage the state. For example, in the <code>changeColor.jsx</code> file.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;

<span class="hljs-keyword">const</span> initialState=<span class="hljs-string">"black"</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> themeSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'theme'</span>,
  <span class="hljs-attr">initialState</span>: { <span class="hljs-attr">value</span>: initialState},
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">changeColor</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>)=&gt;</span>{
      state.value=action.payload
    }
  }
})
<span class="hljs-comment">// Export the reducer function</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { changeColor } = themeSlice.actions
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> themeSlice.reducer
</code></pre>
<p>Let's see what's going on in this code:</p>
<ul>
<li>We will import the <code>useSelector</code> hook from <code>react-redux</code> to get data from the Redux store. This helps us get the current color value from the state.</li>
<li>We will import the <code>useDispatch</code> hook from <code>react-redux</code> to send actions to the Redux store. This allows us to update the color value in the state.</li>
<li>And finally import the <code>Color.js</code> file, which contains the Redux logic, including the reducer and the action for changing the color.</li>
</ul>
<p>Then:</p>
<ol>
<li>We get the current color from the Redux store using the <code>useSelector</code> hook.</li>
<li>We render an input element where users can type their desired color.</li>
<li>We define an event handler to handle changes to the input value. When the user types a color in the input, this event handler will be called.</li>
<li>When the user clicks the "Change Color" button, the event handler dispatches an action to the Redux store with the updated color value.</li>
</ol>
<p>With these changes, the <code>ChangeColor</code> component now uses Redux to manage the state. Users can change the color of the displayed text by typing their desired color in the input field and clicking the "Change text color" button.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { changeColor } <span class="hljs-keyword">from</span> <span class="hljs-string">'../features/Color'</span>;

<span class="hljs-keyword">const</span> ChangeColor = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// State to hold the selected color</span>
  <span class="hljs-keyword">const</span> [color, setColor] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-comment">// Accessing the dispatch function from react-redux</span>
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-comment">// Accessing the theme color value from the Redux store</span>
  <span class="hljs-keyword">const</span> themeColor = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.theme.value);

  <span class="hljs-comment">// Event handler for the input change</span>
  <span class="hljs-keyword">const</span> handleColorChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setColor(e.target.value);
  };

  <span class="hljs-comment">// Event handler for the button click</span>
  <span class="hljs-keyword">const</span> handleButtonClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Dispatching the changeColor action with the selected color</span>
    dispatch(changeColor(color));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> <span class="hljs-attr">themeColor</span> }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Progressively effective resources via business metrics.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'inputBtn-container'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'input'</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleColorChange}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleButtonClick}</span>&gt;</span>
          Change text color
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChangeColor;
</code></pre>
<p>Here's the output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/chrome_LDhsOmTm5O-1.gif" alt="Modified State using Redux" width="600" height="400" loading="lazy">
<em>Modified State using Redux</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The article covers two state management solutions: the <code>useState()</code> hook for small to medium apps and <code>Redux</code> for larger ones. </p>
<p>When choosing which to use, consider factors like app complexity, team size, and performance needs. Understanding both approaches will help you make the right choice.</p>
<p>You can read the <a target="_blank" href="https://redux.js.org/">Redux documentation</a> to learn more.</p>
<p>If you found this article helpful, share it with others who may also find it interesting. </p>
<p>You can also stay updated on my latest projects by following me on <a target="_blank" href="https://https//twitter.com/ijaydimples">Twitter</a> and <a target="_blank" href="https://https//www.linkedin.com/in/ijeoma-igboagu/">LinkedIn</a>.</p>
<p>Thank you for reading💖.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ State Management in React –Props vs the Context API ]]>
                </title>
                <description>
                    <![CDATA[ Figuring out state management in React applications can feel like trying to find your way through a labyrinth. You'll constantly be searching for the most efficient, scalable, and maintainable solution.  The journey often leads to two primary paths: ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/state-management-in-react-props-vs-context-api/</link>
                <guid isPermaLink="false">66bb8920c32849d18c5cdcab</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Fri, 19 May 2023 14:31:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/Cover-Image-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Figuring out state management in React applications can feel like trying to find your way through a labyrinth. You'll constantly be searching for the most efficient, scalable, and maintainable solution. </p>
<p>The journey often leads to two primary paths: Using Props or the Context API. As you embark on this quest for state management mastery, it's crucial to understand the intricacies, trade-offs, and use cases of each approach. </p>
<p>In this tutorial, we'll delve into the world of React state management, dissecting the advantages and disadvantages of using props and the Context API and providing valuable insights to help you make informed decisions for your application. You'll be able to unravel the mysteries of state management in React and discover which path will lead you to success.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>React Fundamentals such as components, JSX syntax, props, and state.</li>
<li>A familiarity with different state management techniques in React, such as using props and the Context API.</li>
</ul>
<h2 id="heading-what-is-state-management-in-react">What is State Management in React?</h2>
<p>State management refers to the methods and techniques used to handle, organise, and share data within a React application. It involves the systematic management and manipulation of data, ensuring seamless integration and synchronization across various components.</p>
<h2 id="heading-benefits-of-react-state-management">Benefits of React State Management</h2>
<p>State management plays a pivotal role in developing dynamic and interactive applications that need to handle evolving data. This data can come from user interactions or other triggering events. </p>
<p>By implementing robust state management techniques, React applications can maintain data integrity, enhance performance, and provide a smooth user experience.</p>
<h2 id="heading-state-management-using-props">State Management Using Props</h2>
<p>This is a technique where state is managed in a parent component and passed down to child components via <em>props</em>. This approach is suitable for small-scale applications with simple state requirements and a shallow component hierarchy. U</p>
<p>sing props is considered a local state management method, as the state is maintained and shared within a limited scope of closely related components.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Prop-passing-Diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>A diagram illustrating using props to manage state</em></p>
<p>In the diagram above, state is passed from the parent component to the children components via props, allowing the child components to access/manipulate that state.</p>
<h3 id="heading-how-to-implement-state-management-in-react-applications-using-props">How to Implement State Management in React Applications Using Props</h3>
<p>Let's look at an example to illustrate prop usage. First, create a parent component in your React app.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Parent Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>Then, using the <code>useState</code> hook, create a state which will hold the initial state of a message.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">"Hello from the Parent Component!"</span>);
</code></pre>
<p>To style the examples going forward, use the styles below:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Itim&amp;display=swap"</span>);

<span class="hljs-selector-class">.App</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}

* {
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}
<span class="hljs-selector-tag">body</span>,
<span class="hljs-selector-tag">input</span>,
<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Itim"</span>, cursive;
  <span class="hljs-attribute">color</span>: burlywood;
}
<span class="hljs-selector-tag">h1</span>,
<span class="hljs-selector-tag">h2</span>,
<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
}

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">background</span>: none;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#333</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.dark</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#333</span>;
}
</code></pre>
<p>Here’s how the parent component looks so far:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Initial-Parent-component-look.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initial Parent component look</em></p>
<p>Next, create a child component which will take in the state passed from the parent.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message from parent: <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>In order for the child component to access the message state declared in the parent component, first import and embed the child component in the parent component like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">"./ChildComponent"</span>;

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">"Hello from the Parent Component!"</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Parent Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>To pass the message state to the child component as a prop, you use a name property (whatever you want your props name to be in the child component) followed an equality sign, then a pair of curly brackets. In the curly brackets, pass in the data you want to move between components.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">"./ChildComponent"</span>;

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">"Hello from the Parent Component!"</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Parent Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">message</span>=<span class="hljs-string">{message}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>To access the message state in your child component, pass in the props keyword as an argument in your child component function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(props);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message from parent: <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>Taking a look at the props in the console now gives the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Confirming-succesful-prop-passing.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confirming successful props passing by logging the props object to the console</em></p>
<p>To read the value of <em>message</em> in the child component, use dot notation to access the message property.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(props);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message from parent: {props.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
       <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>That updates the page to look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/After-successfully-passing-message-prop.png" alt="Image" width="600" height="400" loading="lazy">
<em>After successfully passing the message prop</em></p>
<p>To take this example further, let’s update the state of <em>message</em> from the child component. Start by creating a function that updates the state of <em>message</em> in the parent component:</p>
<pre><code class="lang-js"> <span class="hljs-keyword">const</span> updateMessage = <span class="hljs-function">(<span class="hljs-params">newMessage</span>) =&gt;</span> {
    setMessage(newMessage);
  };
</code></pre>
<p>Then pass that function as a prop to the child component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">"Hello from the Parent Component!"</span>);

  <span class="hljs-keyword">const</span> updateMessage = <span class="hljs-function">(<span class="hljs-params">newMessage</span>) =&gt;</span> {
    setMessage(newMessage);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Parent Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">message</span>=<span class="hljs-string">{message}</span> <span class="hljs-attr">updateMessage</span>=<span class="hljs-string">{updateMessage}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>Then use an input field whose value is initially set to the current value of the message prop:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(props);


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message from parent: {props.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{props.message}/</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>To update the value in the <em>message</em> state, use an <em>onChange</em> event to target the current value in the input field and set that to the value in the message state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(props);
  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    props.updateMessage(e.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message from parent: {props.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{props.message}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>To confirm successful state management, let’s update the value in the input field on the browser.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Succesful-Stete-Management-with-Props.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Successful state management with Props</em></p>
<p>Thus shows successful state management using props.</p>
<h3 id="heading-benefits-of-using-props-for-state-management">Benefits of Using Props for State Management</h3>
<ul>
<li>Simplicity: The application of props in state management presents a simple method to transfer data between components. This approach eliminates the need for supplementary libraries or complex configurations, making it a beginner-friendly option.</li>
<li>Readability: Using props to transmit data ensures clarity regarding the origin and destination of the information. This transparency helps simplify code interpretation and comprehension.</li>
<li>One-Way Data Flow: The unidirectional data flow characteristic of React's props allows data to transition from the parent component to its child. This streamlined movement helps trace data sources and troubleshoot any issues tied to state alterations.</li>
<li>Reusability: Components that rely solely on props (often referred to as stateless components) can be easily reused across different parts of an application. Because they don't manage their own state and only display data based on what they receive through props, they're more predictable and easier to test.</li>
</ul>
<h3 id="heading-drawbacks-of-using-props-for-state-management">Drawbacks of Using Props for State Management</h3>
<ul>
<li>Prop Drilling: This is when you need to pass props through multiple components to reach the ones that actually use them. This can make your code more difficult to maintain and understand, as each intermediate component needs to forward the props.</li>
<li>Lack of State Control: Props are read-only, and child components cannot modify the props they receive from their parent component. To update a prop, you have to lift the state up to the parent or use callback functions, which can become complex in larger applications.</li>
<li>Difficulty in Global State Management: Props work well for parent-child communication but can become cumbersome when you need to share state across many components or across sibling components. It becomes challenging to keep everything in sync.</li>
<li>Testing and Debugging: While stateless components are generally easier to test, when props are used extensively for state management debugging can be challenging. This is because state changes are more scattered across components, making it harder to track where a state change originated.</li>
</ul>
<h2 id="heading-state-management-using-the-context-api">State Management Using the Context API</h2>
<p>The Context API is a React feature that allows sharing data between components without explicitly passing props through each level of the component tree (prop drilling). It allows you to create a global state that can be accessed by any component in your application, regardless of its position in the component hierarchy.</p>
<p>The Context API consists of two main parts: the <em>context provider</em> and the <em>context consumer</em>.</p>
<h4 id="heading-the-context-provider">The Context Provider</h4>
<p>The context provider is responsible for creating and managing the global state. It wraps a section of your component tree and makes the state available to all the components within that tree.</p>
<p>To create a context, you use the <em>createContext</em> function from the React module.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</code></pre>
<p>This function returns a Context object containing a Provider component and a Consumer component.</p>
<p>The Provider component is used to wrap the section of your component tree where you want to make the context available (that is, the component(s) you want to make the data available to).</p>
<p>The Consumer component is used to access the shared data within your components.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Context-Wrapping-Diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>A diagram illustrating using Context API to wrap a React App</em></p>
<p>The diagram above demonstrates that the entire application has been wrapped in a context, which allows all components to access the data from the context without requiring it to be explicitly passed down as a prop from the parent component.</p>
<h3 id="heading-how-to-implement-state-management-in-react-applications-using-the-context-api">How to Implement State Management in React Applications using the Context API</h3>
<p>Using an example to illustrate the use of Context API, let’s create a theme switcher that toggles between light and dark modes.</p>
<p>First, create three sibling components (Sibling Components A, B and C). Then create a ThemeContext.jsx file, importing the createContext function from React, and setting the default value of the context to the default theme.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createContext} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> ThemeContext = createContext({
  <span class="hljs-attr">theme</span>: <span class="hljs-string">"light"</span>,
});
</code></pre>
<p>Next, create a provider component which wraps the components you want the values in the context to be available to, using the children prop.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {

    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span> 
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ThemeContext;
</code></pre>
<p>After that, create a state that holds the default value of the theme using <em>useState.</em></p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">"light"</span>);
</code></pre>
<p>Then return the context provider (which wraps the children prop), and pass in the values you want to make available to the wrapped components.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(<span class="hljs-string">"light"</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">theme</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>To ensure that the ThemeContext and its values are accessible to all descendant components within the component tree, import the sibling components in the App component and wrap them with the <em>ThemeProvider</em> component, imported from <em>ThemeContext</em>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { ThemeProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;
</code></pre>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentA</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentB</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentC</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>For confirmation, import the <em>ThemeContext</em> in all sibling components. Then using the useContext hook, which accepts a context object (<em>ThemeContext</em>), we extract the value of <em>theme</em> and log it to the console.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ThemeContext <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SiblingComponentA</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme } = useContext(ThemeContext);
  <span class="hljs-built_in">console</span>.log(“SiblingComponentA”, theme);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
        Sibling Component A
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ThemeContext <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SiblingComponentB</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme } = useContext(ThemeContext);
  <span class="hljs-built_in">console</span>.log(“SiblingComponentB”, theme);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
        Sibling Component B
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ThemeContext <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SiblingComponentC</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme } = useContext(ThemeContext);
  <span class="hljs-built_in">console</span>.log(“SiblingComponentC”, theme);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
        Sibling Component C
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Confirming-succesful-context-passing.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confirming successful context passing</em></p>
<p>And with that, you’ve successfully passed data to components without moving it through its parent via props.</p>
<p>To take this example further, let’s update the state of <em>theme</em> from the <em>themeContext</em>.</p>
<p>In your <em>ThemeProvider</em> function, create a toggle function which compares the previous state of the theme with a value and toggles it based on the result of the comparison.</p>
<pre><code class="lang-js"> <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> {
    setTheme(<span class="hljs-function">(<span class="hljs-params">prevTheme</span>) =&gt;</span> (prevTheme === <span class="hljs-string">"light"</span> ? <span class="hljs-string">"dark"</span> : <span class="hljs-string">"light"</span>));
  };
</code></pre>
<p>Next, pass the <em>toogleTheme</em> function to the <em>ThemeContext.Provider</em>, making it available to all the descendants of the <em>ThemeProvider</em>.</p>
<pre><code class="lang-js"> &lt;ThemeContext.Provider value={{ theme, toggleTheme }}&gt;
      {children}
 &lt;/ThemeContext.Provider&gt;
</code></pre>
<p>To utilize this functionality, create a <em>ThemeButton</em>, and nest it in the App component.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentA</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentB</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">SiblingComponentC</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ThemeButton</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the <em>ThemeButton</em> component, import the <em>ThemeContext</em> component, and use the <em>useContext</em> hook to extract the <em>toggleTheme</em> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ThemeContext <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ThemeButton</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { toggleTheme } = useContext(ThemeContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> &gt;</span>ThemeButton<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}
</code></pre>
<p>Then attach an onClick event to the button, which calls the <em>toggleTheme</em> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggleTheme}</span>&gt;</span>ThemeButton<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
</code></pre>
<p>To test your functionality, observe the console while you click on the theme button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Theme-switching-with-Context-API.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Theme Switching with context API</em></p>
<p>And violà! The theme value is updated on each click and synchronous on all components.</p>
<p>For added flair, you can add conditionals to each component and toggle its colour based on the current theme, like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ThemeContext <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeContext"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SiblingComponentA</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { theme } = useContext(ThemeContext);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sibling Component A"</span>, theme);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">theme</span> === <span class="hljs-string">"dark"</span> ? "<span class="hljs-attr">dark</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">light</span>"}`}&gt;</span>
        Sibling Component A
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Which results in the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Theme-Color-Switching-with-Context-API.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Theme Color switching with Context API</em></p>
<h3 id="heading-advantages-of-using-context-api-for-state-management">Advantages of Using Context API for State Management</h3>
<ul>
<li>Global Data Sharing: Context provides a way to share state across multiple components without the need to pass props down through intermediate components. It allows you to establish a global data flow in your application, making the state accessible to any component that needs it.</li>
<li>Avoids Prop Drilling: Prop drilling occurs when you need to pass data through multiple layers of components. With Context, you can avoid this issue by providing the data directly to the components that need it, regardless of their position in the component tree.</li>
<li>Reduces Coupling: Using Context allows components to be more loosely coupled since they don't need to rely on specific props being passed down. Components can focus on their own responsibilities without having to worry about passing data down through multiple levels.</li>
<li>Cleaner and More Maintainable Code: By centralizing the state in a single place, the code becomes cleaner and more maintainable. It avoids cluttering components with irrelevant state management logic and keeps the concerns separated.</li>
</ul>
<h3 id="heading-drawbacks-of-using-context-api-for-state-management">Drawbacks of Using Context API for State Management</h3>
<ul>
<li>Reduced Performance: Updating the context value can potentially cause unnecessary re-renders in consuming components, even if the changes are not relevant to them. This can impact performance, especially in larger component trees. Careful consideration of when and how to update the context value is necessary to mitigate this issue.</li>
<li>Complexity in Testing: Testing components that consume context can be more complex compared to testing components with props-based state management. Mocking or providing the correct context values during testing may require additional setup and can make unit tests more cumbersome.</li>
<li>Potential for Overuse: The simplicity and ease of use of the Context API can lead to its overuse, causing excessive coupling between components and making the codebase harder to understand and maintain. Overusing context for every piece of shared state, especially for unrelated concerns, can make the codebase less modular and harder to reason about.</li>
<li>Lack of Type Safety: Context values are not type-checked by default, which means that incorrect usage or changes in the shape of the context value may not be caught by the compiler or development tools. This can lead to runtime errors and debugging challenges.</li>
</ul>
<h2 id="heading-comparing-props-and-the-context-api">Comparing Props and the Context API</h2>
<h3 id="heading-use-cases-for-props">Use Cases for Props</h3>
<ul>
<li>Local Component State: When the state is only needed within a specific component and doesn't need to be shared with other components, managing it through the local component state using props is a straightforward and efficient approach.</li>
<li>Parent-to-Child Data Flow: Props are ideal for passing data from parent components to their child components. This allows parent components to control and provide the necessary data to their child components.</li>
<li>Component Composition: Props facilitate the composition of components by allowing you to customize their behavior and appearance based on the data passed as props. This promotes reusability and flexibility in building component-based architectures.</li>
<li>Explicit Data Flow: Using props offers a clear and explicit data flow, where the flow of data can be easily traced by following the props passed down through the component hierarchy. This makes it easier to understand how data is flowing and being consumed by different components.</li>
</ul>
<h3 id="heading-use-cases-for-the-context-api">Use Cases for the Context API</h3>
<ul>
<li>Global or Application-Wide State: When you need to share state or data across multiple components in different parts of your application, the Context API simplifies the process by providing a centralized way to manage and access that state.</li>
<li>Deeply Nested Components: The Context API becomes more advantageous when dealing with deeply nested components. It helps avoid prop drilling through multiple layers of components by providing a direct way for child components to access the context without passing props through intermediate components.</li>
<li>Cross-Component Communication: If you have components that are not directly related in the component tree but need to share data, the Context API facilitates cross-component communication by providing a shared context that can be accessed by any interested component.</li>
<li>Dynamic or Changing State: When the state needs to be updated frequently or dynamically, the Context API provides a convenient way to manage and update the state value. Components consuming the context will automatically re-render when the context value changes.</li>
</ul>
<h3 id="heading-alternative-state-management-solutions">Alternative State Management Solutions</h3>
<p>Besides props and the Context API, there are several alternative state management solutions available in the React ecosystem. Let's explore a few popular options:</p>
<ul>
<li><a target="_blank" href="https://redux.js.org/">Redux</a>: A centralized state management library with a single immutable state tree and strict unidirectional data flow.</li>
<li><a target="_blank" href="https://mobx.js.org/README.html">MobX</a>: A reactive state management library that tracks state changes using observable data structures.</li>
<li><a target="_blank" href="https://tanstack.com/query/v3/">React Query</a>: A data-fetching library for handling asynchronous data in React, providing caching and background updates.</li>
<li><a target="_blank" href="https://www.apollographql.com/docs/react/">Apollo Client:</a> A full-featured GraphQL client for managing state through GraphQL queries and mutations.</li>
<li><a target="_blank" href="https://docs.pmnd.rs/zustand/getting-started/introduction">Zustand</a>: A lightweight state management library that uses React hooks and the Context API for simplicity and performance.</li>
</ul>
<p>Each of these state management solutions has its own strengths, features, and trade-offs. Deciding which one to use depends on factors such as the complexity of your application, the scalability requirements, the team's familiarity with the library, and the specific needs of your project.</p>
<p> It's important to evaluate and select the one that best fits your use case to effectively manage state in your React application.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>When considering state management in React, the choice between props and the Context API depends on the scale, complexity, and data flow requirements of your project. </p>
<p>Props are suitable for local component state and controlled data flow within parent and child components. The Context API is ideal for global or application-wide state, deep component nesting, and cross-component communication. </p>
<p>Both approaches can be used together or in combination with other state management libraries to create a tailored solution that meets your specific needs. Understanding the trade-offs will help you build efficient and maintainable React applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Redux and Redux Toolkit – Tutorial for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ When I started learning Redux, I found it challenging to wrap my head around the concepts. Despite reading many online resources, I struggled to grasp the core ideas.  While the online tutorials and guides provided helpful information, I needed more ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/redux-and-redux-toolkit-for-beginners/</link>
                <guid isPermaLink="false">66bd90551bb54b9103c678bb</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Boateng Dickson ]]>
                </dc:creator>
                <pubDate>Thu, 04 May 2023 14:20:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/redux-for-beginners1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When I started learning Redux, I found it challenging to wrap my head around the concepts. Despite reading many online resources, I struggled to grasp the core ideas. </p>
<p>While the online tutorials and guides provided helpful information, I needed more clarity to really understand Redux.</p>
<p>But with persistence and practice, I eventually gained a better understanding of Redux's key concepts and successfully implemented them in my projects.</p>
<p>In this article, I will explain Redux in the simplest possible way. As someone who initially struggled with understanding Redux, I know how frustrating it can be to learn a new concept. But I hope this article will help make the concepts of Redux more accessible to beginner learners.</p>
<p>We will also delve into Redux Toolkit, a collection of tools that simplify using Redux. These tools help make Redux less daunting and easier to use.</p>
<h2 id="heading-what-is-redux">What is Redux?</h2>
<p>Redux is a state management library that allows you to manage the state of your JavaScript applications more efficiently and predictably.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-165.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Imagine you are building a house and need to keep track of all the materials you use and how much money you spend. Instead of keeping track of everything in your head or on a piece of paper, you could use a ledger to keep track of every transaction. Redux works similarly by keeping track of your application's state in a single place called the "store."</p>
<p>Let's say you're building an e-commerce site. You may need to keep track of the items in a user's cart, their payment information, and their shipping details. </p>
<p>Instead of passing this information from component to component using props, Redux allows you to store them in one central location where they can be easily accessed and updated. This makes it easier to manage complex states and keep your application organized.</p>
<p>It's important to note that Redux is not limited to React and you can use it with other frameworks or even vanilla JavaScript.</p>
<h2 id="heading-why-should-i-use-redux">Why Should I Use Redux?</h2>
<p>Redux can help simplify the state management process, especially when dealing with complex and interconnected components. Here are some reasons why you might want to use Redux in your application:</p>
<ol>
<li><strong>Centralized state management:</strong> With Redux, you can maintain the state of your entire application in a single store, making it easier to manage and access data across components.</li>
<li><strong>Predictable state updates:</strong> Redux has a clear flow of data, which means changes to the state can only happen when you create an action and send it through Redux. This makes it easy to understand how your application's data will change in response to user actions.</li>
<li><strong>Easier debugging:</strong> With Redux DevTools, you have a clear record of all the changes to your application's state. This makes locating and fixing issues in your code easier, saving you time and effort in the debugging process.</li>
<li><strong>Better performance:</strong> By minimizing the number of state updates and reducing the need for prop drilling, Redux helps improve your application's performance.</li>
</ol>
<h2 id="heading-how-does-redux-work">How Does Redux Work?</h2>
<p>As previously mentioned, Redux enables you to maintain a single centralized store that manages the state of your entire application. All components in your application can access this store and update or retrieve data from it as needed. </p>
<p>The key components that enable this centralized approach to state management are:</p>
<ol>
<li>Store</li>
<li>Actions</li>
<li>Dispatch</li>
<li>Reducers</li>
</ol>
<p>Let’s explore the role of each one:</p>
<h3 id="heading-the-store">The Store</h3>
<p>The Redux store is like a giant container that holds all the data for your application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-167.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Think of the store as a box with different compartments for different data types. You can store any data you want in these compartments, and it can hold various kinds of data, such as strings, numbers, arrays, objects, and even functions.</p>
<p>Also, the store is the single source of truth for your application's state. This means that any component in your application can access it to retrieve and update data.</p>
<h3 id="heading-actions">Actions</h3>
<p>An action is an object that describes what changes need to be made to the state of your application. It sends data from your application to the Redux store and serves as the only way to update the store.</p>
<p>An action must have a "type" property describing the action being performed. This "type" property is typically defined as a string constant to ensure consistency and avoid typos.</p>
<p>In addition to the "type" property, an action can have a "payload" property. The "payload" property represents the data that provides additional information about the action being performed. For example, if an action type is <code>ADD_TASK</code>, the payload might be an object containing a new task item's "id", "text", and "completed status".</p>
<p>Here's an example of an action:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TASK'</span>,
  <span class="hljs-attr">payload</span>: {
    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">text</span>: <span class="hljs-string">'Buy groceries'</span>,
    <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
  }
}
</code></pre>
<p>Note that to create actions, we use action creators. Action creators are functions that create and return action objects.</p>
<p>Here is an example of an action creator that takes in a task's text and returns an action object to add the task to the Redux store:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addTask</span>(<span class="hljs-params">taskText</span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_TASK'</span>,
    <span class="hljs-attr">payload</span>: {
      <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">text</span>: taskText,
      <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>
    }
  }
}
</code></pre>
<p>An appropriate analogy for actions and action creators would be a chef using a recipe. The recipe outlines the required ingredients and instructions to prepare a dish, similar to how an action in Redux specifies the needed details to modify the state of an application. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-171.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this scenario, the chef represents the action creator, who follows the recipe to create the dish, similar to how an action creator creates an action based on predefined properties.</p>
<h3 id="heading-dispatch">Dispatch</h3>
<p>In Redux, dispatch is a function provided by the store that allows you to send an action to update the state of your application. When you call <code>dispatch</code>, the store runs an action through all of the available reducers, which in turn update the state accordingly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-185.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can think of <code>dispatch</code> as a mail carrier who delivers mail to different departments in a large company. Just like how the mail carrier delivers mail to different departments, <code>dispatch</code> delivers actions to various reducers in your Redux store. Each reducer is like a department in the company that processes the mail and updates its own part of the company's data.</p>
<h3 id="heading-reducers">Reducers</h3>
<p>In Redux, a reducer is a function that takes in the current state of an application and an action as arguments, and returns a new state based on the action.</p>
<p>Here's an example of a simple reducer:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">counterReducer</span>(<span class="hljs-params">state = initialState, action</span>) </span>{
  <span class="hljs-keyword">switch</span>(action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
}
</code></pre>
<p>In the above code, we have a simple reducer called "counterReducer" that manages the state of a count variable. It takes in two arguments: <code>state</code> and <code>action</code>. The <code>state</code> argument represents the current state of your application, while the <code>action</code> argument represents the action dispatched to modify the state.</p>
<p>The reducer then uses a switch statement to check the "type" of the action, and based on that type, it updates the state accordingly. </p>
<p>For example, if the action type is "INCREMENT", the reducer returns a new state object with the count incremented by 1. Also, if the action type is "DECREMENT", the reducer returns a new state object with the count decremented by 1.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-172.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>A perfect analogy for a reducer would be a kitchen blender. Just like a blender takes in different ingredients, blends them, and produces a smooth mixture, a reducer takes in the current state of an application and an action, processes them together, and produces a new state.</p>
<h2 id="heading-example-project-real-app-implementation">Example Project – Real App Implementation</h2>
<p>Now that you understand the basics of Redux and how it works, let's create a simple real-world project. For this example, we'll create a basic ToDo List application where you can add and delete tasks.</p>
<h3 id="heading-step-1-how-to-set-up-the-project">Step 1: How to set up the project</h3>
<p>Create a new React project by running the following command in your terminal. Replace <em>"your-project-name"</em> with the name of your project.</p>
<pre><code>npm create vite@latest your-project-name -- --template react

cd your-project-name

npm install
</code></pre><p>The above command sequence will create a new React project using the Vite build tool and install all necessary dependencies.</p>
<h3 id="heading-step-2-how-to-install-redux">Step 2: How to install Redux</h3>
<p>Redux requires a few dependencies for its operations, namely:</p>
<ul>
<li><strong>Redux:</strong> The core library enables the redux architecture.</li>
<li><strong>React Redux:</strong> Simplifies connecting your React components to the Redux store.</li>
<li><strong>Redux Thunk:</strong> Allows you to write asynchronous logic in your Redux actions.</li>
<li><strong>Redux DevTools Extension:</strong> Connects your Redux application to Redux DevTools</li>
</ul>
<p>You can install them using npm, as shown below:</p>
<pre><code>npm install \

redux \

react-redux \

redux-thunk \

redux-devtools-extension
</code></pre><h3 id="heading-step-3-how-to-set-up-reducers">Step 3: How to set up reducers</h3>
<p>Now let's create the reducer for our application. </p>
<p>In the <code>src</code> directory, create a new folder called <code>reducers</code>, and inside that folder, create two new files: <code>index.js</code> and <code>taskReducer.js</code>.</p>
<p>The <code>index.js</code> file represents the root reducer, which combines all the individual reducers in the application. In contrast, the <code>taskReducer.js</code> file is one of the individual reducers that will be combined in the root reducer.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> taskReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./taskReducer"</span>;
<span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;

<span class="hljs-keyword">const</span> rootReducer = combineReducers({
  <span class="hljs-attr">tasks</span>: taskReducer,
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> rootReducer;
</code></pre>
<p>In the above <code>index.js</code> file, we use the <code>combineReducers</code> function to combine all the individual reducers into a single root reducer. In this case, we only have one reducer (<code>taskReducer</code>), so we pass it in as an argument to <code>combineReducers</code>.</p>
<p>The resulting combined reducer is then exported so that other files in the application can import and use it to create the store.</p>
<p>Here's the code for <code>taskReducer</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">tasks</span>: []
};

<span class="hljs-keyword">const</span> taskReducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_TASK'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">tasks</span>: [...state.tasks, action.payload]
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DELETE_TASK'</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">tasks</span>: state.tasks.filter(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> task.id !== action.payload)
      };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> rootReducer;
</code></pre>
<p>Inside the above <code>taskReducer.js</code> file, we define a reducer function that takes two arguments: <code>state</code> and <code>action</code>. The <code>state</code> argument represents the current state of the application, while the <code>action</code> argument represents the action being dispatched to update the state.</p>
<p>The <code>switch</code> statement inside the reducer handles different cases based on the "type" of the action. For example, if the action type is <code>ADD_TASK</code>, the reducer returns a new state object with a new task added to the <code>tasks</code> array. And if the action type is <code>DELETE_TASK</code>, the reducer returns a new state object with the current tasks filtered to remove the task with the specified <code>id</code>.</p>
<h3 id="heading-step-4-how-to-create-the-redux-store">Step 4: How to create the Redux store</h3>
<p>Now that we have our basic setup ready, let's create a new file called <code>store.js</code> in the <code>src</code> directory. This is where you'll define your Redux store:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;
<span class="hljs-keyword">import</span> thunk <span class="hljs-keyword">from</span> <span class="hljs-string">"redux-thunk"</span>;
<span class="hljs-keyword">import</span> { composeWithDevTools } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux-devtools-extension"</span>;

<span class="hljs-keyword">import</span> taskReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./reducers/taskReducer"</span>;

<span class="hljs-keyword">const</span> store = createStore(
  taskReducer,
  composeWithDevTools(applyMiddleware(thunk))
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>The code above sets up a Redux store by creating a new instance of the store using the <code>createStore</code> function. Then, the rootReducer – which combines all the application's reducers into a single reducer – is passed as an argument to <code>createStore</code>. </p>
<p>In addition, the code also uses two other libraries: <code>redux-thunk</code> and <code>redux-devtools-extension</code>. </p>
<p>The <code>redux-thunk</code> library allows you to write asynchronous actions, while the <code>redux-devtools-extension</code> library enables you to use the Redux DevTools browser extension to debug and inspect the state and actions in the store. </p>
<p>Finally, we export the store so we can use it in our application. We use the <code>composeWithDevTools</code> function to enhance the store with the ability to use the Redux DevTools extension, and the <code>applyMiddleware</code> function to apply the thunk middleware to the store."</p>
<h3 id="heading-step-5-how-to-connect-the-redux-store-to-the-application">Step 5: How to connect the Redux Store to the application</h3>
<p>To connect the Redux store to the ToDo application, we need to use the <code>Provider</code> component from the <code>react-redux</code> library.</p>
<p>First, we import the <code>Provider</code> function and the Redux store we created into our <code>main.jsx</code>. Then, we wrap our <code>App</code> component with the <code>Provider</code> function and pass the <code>store</code> as a prop. This makes the Redux store available to all the components inside the <code>App</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./store"</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<h3 id="heading-step-6-how-to-use-redux-devtools">Step 6: How to use Redux DevTools</h3>
<p>Once you've set up the Redux <code>&lt;Provider&gt;</code> in your application, you can start using the Redux DevTools extension. To get started with it, you'll need to download the Redux DevTools Extension for your browser. </p>
<p>After installation, the DevTools will add a new tab to your browser's Developer Tools specifically for Redux.</p>
<p><img src="https://i.imgur.com/QPPsZDT.gif" width="832" height="547" alt="QPPsZDT" loading="lazy"></p>
<p>Clicking on the "State" tab within the Redux DevTools will show you the entire state of your Redux store and any actions that have been dispatched and their payloads. </p>
<p>This can be incredibly useful when debugging your application, as you can inspect the state and actions in real-time.</p>
<h3 id="heading-step-7-how-to-set-up-redux-actions">Step 7: How to set up Redux Actions</h3>
<p>Now that we have everything set up, let's create our actions. As I mentioned before, actions represent something that happened in the application. For example, when a user adds a new task, it triggers an "add task" action. Similarly, when a user deletes a task, it triggers a "delete task" action.</p>
<p>To create the actions, create a new folder called "actions" in the <code>src</code> directory and then create a new file called <code>index.js</code>. This file will contain all of the action creators for our application.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addTodo = <span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">"ADD_TASK"</span>,
    <span class="hljs-attr">payload</span>: {
      <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime(),
      <span class="hljs-attr">text</span>: text,
    },
  };
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> deleteTodo = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">"DELETE_TASK"</span>,
    <span class="hljs-attr">payload</span>: id,
  };
};
</code></pre>
<p>The above code exports two action creators: <code>addTodo</code> and <code>deleteTodo</code>. These functions return an object with a <code>type</code> property that describes the action that has occurred.</p>
<p>In the case of <code>addTodo</code>, the <code>type</code> property is set to <code>"ADD_TASK"</code>, indicating that a new task has been added. The <code>payload</code> property contains an object with the new task's <code>id</code> and <code>text</code> values. The <code>id</code> is generated using the <code>new Date().getTime()</code> method creates a unique identifier based on the current timestamp.</p>
<p>In the case of <code>deleteTodo</code>, the <code>type</code> property is set to <code>"DELETE_TASK"</code>, indicating that a task has been deleted. The <code>payload</code> property contains the <code>id</code> of the task to be deleted.</p>
<p>These action creators can be dispatched to the Redux store using the <code>dispatch()</code> method, which will trigger the corresponding reducer function to update the application state accordingly.</p>
<h3 id="heading-step-8-how-to-dispatch-actions">Step 8: How to dispatch actions</h3>
<p>Now that we have created the necessary actions, we can move on to creating the components that will dispatch these actions. </p>
<p>Let's create a new folder named "components" inside the <em>src</em> directory. Inside this folder, we will create two new files: <code>Task.jsx</code> and <code>TaskList.jsx</code>.</p>
<p>The <code>Task.jsx</code> component will be responsible for adding tasks. But before we proceed, we need to import the following into the file:</p>
<ul>
<li><em>addTodo action</em>: To add new tasks to the state.</li>
<li><em>useDispatch hook</em>: To dispatch the <code>addTodo</code> action.</li>
<li><em>useRef</em>: Allows us to obtain a reference to HTML elements.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { addTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;
</code></pre>
<p>Once we have imported these necessary components, we can proceed to write code for <code>Task.jsx</code>. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Task = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> dispatch = useDispatch();
  <span class="hljs-keyword">const</span> inputRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addNewTask</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> task = inputRef.current.value.trim();
    <span class="hljs-keyword">if</span> (task !== <span class="hljs-string">""</span>) {
      dispatch(addTodo(task));
      inputRef.current.value = <span class="hljs-string">""</span>;
    }
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"task-component"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"add-task"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Add task here..."</span>
          <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"taskInput"</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{addNewTask}</span>&gt;</span>Add task<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Task;
</code></pre>
<p>In the code above, we created a component consisting of an input field and a button. When a user clicks on the "Add task" button, the <code>addNewTask</code> function is executed. This function uses the <code>useRef</code> hook to obtain the input field's value, removes any leading or trailing whitespaces, and then dispatches the <code>addTodo</code> action with the new task as the payload.</p>
<p>Now, let's move on to the <code>TaskList.jsx</code> component, responsible for rendering the list of tasks and handling task deletions. To achieve this, we need to import the following:</p>
<ul>
<li>The <strong>useSelector hook</strong> provides access to the state from the Redux store.</li>
<li>The <strong>deleteTodo action</strong>, is responsible for removing a task from the list of tasks in the Redux store.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { deleteTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;
</code></pre>
<p>We will now write code for <code>TaskList.jsx</code> that maps over the tasks array and renders each task:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { deleteTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">'../actions'</span>;

<span class="hljs-keyword">const</span> TaskList = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> tasks = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.tasks);
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">const</span> handleDelete = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {
    dispatch(deleteTodo(id));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tasklist"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"display-tasks"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Your tasks:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tasks"</span>&gt;</span>
          {tasks.map((task) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"task"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{task.id}</span>&gt;</span>
              {task.text}
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"delete-btn"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleDelete(task.id)}
              &gt;
                delete
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TaskList;
</code></pre>
<p>Here, the component loops over each task in the tasks array and displays text and a delete button. When the user clicks the delete button, the <code>handleDelete</code> function is called, dispatching the <code>deleteTodo</code> action with the task's <code>id</code> as the payload.</p>
<p>Finally, import the components into your <code>App.jsx</code> file and render them.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Task <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Task"</span>;
<span class="hljs-keyword">import</span> TaskList <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/TaskList"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Task</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TaskList</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-step-9-styling">Step 9: Styling</h3>
<p>For styling, copy the contents of this <a target="_blank" href="https://gist.githubusercontent.com/dboatengg/ea07e95167aec1af97084651128ea8e9/raw/d5b0e5611c4a82e46ad4bc2f33defefd4ce9937a/index.css">gist</a> and paste it into your <code>index.css</code> file. The focus of this guide is only on functionality and not on styling. Therefore, only basic styles were included to ensure the application looked presentable.</p>
<h3 id="heading-final-result">Final Result</h3>
<p>After implementing everything, the final result of our ToDo List application should look something like this:</p>
<p><img src="https://i.imgur.com/AACNPOW.gif" width="680" height="350" alt="AACNPOW" loading="lazy"></p>
<p>As shown above, we can add tasks by entering texts in the input field and clicking the "Add task" button. We can also delete tasks by clicking the "delete" button next to each task.</p>
<p>The state and actions of the application can also be easily tracked and inspected using Redux DevTools. This feature helps debug and understand how the app works under the hood.</p>
<p>With that, you now have a fully functional ToDo application powered by Redux! The source code for the app is available on this <a target="_blank" href="https://github.com/dboatengg/redux-tutorial">GitHub repository</a>.</p>
<p>Finally, it's important to note that an application's state is stored in memory when using Redux. Therefore, the state will be lost if a user refreshes the page or navigates away from the app.</p>
<p>So, to keep information even after a user leaves or closes the page, you need to store that information somewhere else outside of the app's memory. Various techniques, such as local or server-side storage, can be used to accomplish this.</p>
<p>Congratulations! You now have a good grasp of how to integrate Redux into your React applications. In the next section, we will explore Redux Toolkit and discover how it can simplify the process of writing Redux code with less effort.</p>
<h2 id="heading-how-to-use-redux-toolkit">How to Use Redux Toolkit</h2>
<p>Writing Redux code can become complex and verbose, particularly as the size of an application grows. As the number of reducers and actions increase, it can become challenging to manage the different pieces and keep track of everything.</p>
<p>Fortunately, Redux Toolkit provides a solution to this problem. It gives a more streamlined and efficient way to manage the state of your application by abstracting away some of the more complex and repetitive aspects of Redux, such as creating reducers and actions.</p>
<h3 id="heading-advantages-of-redux-toolkit">Advantages of Redux Toolkit</h3>
<p>Redux Toolkit provides several advantages over traditional Redux:</p>
<ul>
<li>It is easier to set up and requires fewer dependencies.</li>
<li>Reduces boilerplate code by allowing the creation of a single file known as "slice" that combines actions and reducers.</li>
<li>Provides sensible defaults for commonly used features, such as Redux Thunk and Redux DevTools. This means that you don't have to spend time configuring these features yourself, as they are already built into Redux Toolkit.</li>
<li>It uses the immer library under the hood, which enables direct state mutation and eliminates the need for manually copying the state <code>{...state}</code> with every reducer.</li>
</ul>
<p>In the next sections, we will explore how to use Redux Toolkit to simplify the Redux code for the ToDo application we built earlier.</p>
<h3 id="heading-how-to-set-up-redux-toolkit">How to set up Redux Toolkit</h3>
<p>To use Redux Toolkit in your React application, you need to install two dependencies: <code>@reduxjs/toolkit</code> and <code>react-redux</code>. </p>
<p>The <code>@reduxjs/toolkit</code> package provides the necessary tools to simplify Redux development, while <code>react-redux</code> is needed to connect your Redux store to your React components. </p>
<pre><code>npm install @reduxjs/toolkit react-redux
</code></pre><h3 id="heading-how-to-create-a-slice">How to create a slice</h3>
<p>Once you have installed the needed dependencies, create a new "slice" using the <code>createSlice</code> function. A slice is a portion of the Redux store that is responsible for managing a specific piece of state.</p>
<p>Think of the Redux store as a cake, where each slice represents a specific piece of data in the store. By creating a slice, you can define the behaviour of the state in response to particular actions using reducer functions.</p>
<p>To create a slice to manage our ToDo application, create a new file named <code>src/features/todo/todoSlice.js</code> and add the following code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;

<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">tasks</span>: [],
};

<span class="hljs-keyword">const</span> todoSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"todo"</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.tasks.push({ <span class="hljs-attr">id</span>: <span class="hljs-built_in">Date</span>.now(), <span class="hljs-attr">text</span>: action.payload });
    },
    <span class="hljs-attr">deleteTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.tasks = state.tasks.filter(<span class="hljs-function">(<span class="hljs-params">task</span>) =&gt;</span> task.id !== action.payload);
    },
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, deleteTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<p>The above code defines a slice named <code>todoSlice</code>, with an <code>initialState</code> object that contains an empty array of tasks. </p>
<p>The <code>reducers</code> object defines two reducer functions: <code>addTask</code> and <code>deleteTask</code>. <code>addTask</code> pushes a new task object into the <code>tasks</code> array, and <code>deleteTask</code> removes a task from the <code>tasks</code> array based on its <code>id</code> property.</p>
<p>The <code>createSlice</code> function automatically generates action creators and action types based on the names of the reducer functions you provide. So you don't have to define the action creators yourself manually.</p>
<p>The <code>export</code> statement exports the generated action creators, which can be used in other parts of your app to dispatch actions to the slice.</p>
<p>And finally, the <code>todoSlice.reducer</code> function handles all actions automatically generated based on the reducer objects provided to the <code>createSlice</code> function. By exporting it as the default, you can combine it with other reducers in your application to create a complete Redux store.</p>
<h3 id="heading-how-to-set-up-redux-store">How to set up Redux Store</h3>
<p>Creating a Redux store is much simpler with Redux Toolkit. </p>
<p>The most basic way to create a store is to use the <code>configureStore()</code> function, which automatically generates a root reducer for you by combining all the reducers defined in your application. </p>
<p>To create a store for the application, add a file named <code>src/store.js</code> and add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;
<span class="hljs-keyword">import</span> todoReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./features/todo/todoSlice"</span>;

<span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">todo</span>: todoReducer,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>In this example, we first import the <code>configureStore</code> function from the <code>@reduxjs/toolkit</code> package, and the  <code>todoReducer</code> function from a separate file.</p>
<p>Then, we create a <code>store</code> object by calling <code>configureStore</code> and passing it an object with a <code>reducer</code> property. The <code>reducer</code> property is an object that maps reducer slice names to their corresponding reducer functions. In this case, we have one reducer slice called <code>todo</code>, and its corresponding reducer function is <code>todoReducer</code>.</p>
<p>Finally, we export the <code>store</code> object so that it can be imported and used in other parts of the application.</p>
<h3 id="heading-how-to-provide-the-redux-store-to-react">How to provide the Redux store to React</h3>
<p>To make your Redux store available to the React components in your application, import the Provider component from the <code>react-redux</code> library and wrap your root component (usually <code>&lt;App&gt;</code>) with it. </p>
<p>The Provider component takes in the store as a prop and passes it down to all the child components that need access to it.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App.jsx"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./store.js"</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<h3 id="heading-create-components">Create components</h3>
<p>You can now create React components such as <code>Task.jsx</code> and <code>TaskList.jsx</code> that use the <code>useSelector</code> hook to access the current state from the store. Similarly, you can use the <code>useDispatch</code> hook to dispatch actions to update the store, just as you did in plain Redux. </p>
<p>You should now have the same app as before with a few updates from Redux Toolkit and a lot less code to maintain.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you've followed along with this tutorial, you should now have a solid understanding of Redux, both the traditional approach and the simplified version using Redux Toolkit. </p>
<p>I hope you found this article helpful and informative. I know it was a lot of material to cover, but I hope it serves as a comprehensive resource for beginners and intermediate learners seeking to learn Redux. </p>
<p>If you want to experiment with the code we've covered in this article, you can access it in the <a target="_blank" href="https://github.com/dboatengg/redux-tutorial">GitHub repository</a> provided. Feel free to use it as a starting point for your own applications or as a reference as you continue to learn and explore the world of Redux.</p>
<p>Thank you for reading, and happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Redux Toolkit to Manage State in Your React Application ]]>
                </title>
                <description>
                    <![CDATA[ State management is one of the most important things you'll deal with in front end development.  You can manage state in React in various ways. Some examples include using state in class components, using React hooks such as useState and useEffect ho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-redux-toolkit-to-manage-state-in-react-apps/</link>
                <guid isPermaLink="false">66ba2f4d54ccc2d852dc891a</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Quincy Oghenetejiri Ukumakube ]]>
                </dc:creator>
                <pubDate>Mon, 24 Apr 2023 21:38:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/Freecodecamp-Banner.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is one of the most important things you'll deal with in front end development. </p>
<p>You can manage state in React in various ways. Some examples include using state in class components, using React hooks such as useState and useEffect hook, using the Context API, or using Redux. </p>
<p>In this article I will show you how to use the Redux toolkit for state management in React. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Basic knowledge of React (beginners are welcome) and JavaScript is required.</li>
<li>Have Node installed so you can download the package using <code>npm</code>.</li>
</ul>
<h2 id="heading-what-is-redux-toolkit">What is Redux toolkit?</h2>
<p>Redux Toolkit is a set of tools you can use for state management in React in place of Redux. The Redux team created it. </p>
<p>Redux Toolkit offers a standardized approach to building Redux code and comes with libraries and tools that make it simpler to create scalable, maintainable, and effective Redux code.</p>
<h3 id="heading-how-is-it-different-from-the-old-redux">How is it different from the old Redux?</h3>
<p>Redux toolkit is different from Redux in a few ways. First, it has less boilerplate code, and it has decent support. It also works best with functional components (unlike Redux which works best with class components).</p>
<p>There are various reasons why you should use Redux toolkit over Redux for state management: </p>
<ol>
<li>Less boilerplate code than Redux.</li>
<li>You don't have to set up thunk manually in Redux toolkit as it comes with <code>createAsyncThunk</code>. This enables you to perform async operations.</li>
<li>Enhancing developer experience: Redux Toolkit includes a number of tools and utilities that can enhance the developer experience, such as the ability to use Redux DevTools out-of-the-box.</li>
<li>Redux hooks like useSelector and useDispatch make your code shorter and easier to read/write.</li>
<li>Improving performance: Redux Toolkit includes a built-in memoization feature that can help improve the performance of your Redux application by reducing unnecessary re-renders.</li>
</ol>
<p>In summary, Redux Toolkit is a great choice for developers who want to simplify their Redux code and improve performance, while also enhancing the developer experience. It can be particularly useful in larger, more complex applications where managing state can become difficult.</p>
<h2 id="heading-how-to-get-started-with-redux-toolkit">How to Get Started with Redux Toolkit</h2>
<p>For this project, you won't use <code>create-react-app</code> to create your React app. Instead, you'll use Vite and React plugins. This is because CRA is no longer recommended by the React docs.</p>
<p>To create your app, run the code below in your terminal:</p>
<pre><code>npm create vite@latest my-app --template react
</code></pre><p>Next, run the following commands in the terminal:</p>
<pre><code>cd my-app
npm install
npm run dev
</code></pre><h3 id="heading-how-to-install-redux-toolkit">How to install Redux Toolkit</h3>
<p>To make use of Redux Toolkit in your project, run the code below in your terminal:</p>
<pre><code>npm install @reduxjs/toolkit react-redux
</code></pre><h3 id="heading-how-to-create-a-redux-store">How to create a Redux store</h3>
<p>After the installation is complete, create a file named <code>src/redux/store.jsx</code> . Import <code>configureStore</code> from Redux Toolkit and then create an empty Redux store which will be exported like you can see in the code below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {},
})
</code></pre>
<p>This code creates a Redux store, and also automatically configures the Redux DevTools extension so that you can inspect the store while developing.</p>
<h3 id="heading-how-to-connect-the-redux-store-to-react">How to connect the Redux Store to React</h3>
<p>After you've created the store, you will have to wrap your <code>&lt;App/&gt;</code> with a <code>&lt;Provider/&gt;</code> which will be imported from react-redux. Also the store you created above will be passed in into the provider as a prop.</p>
<pre><code class="lang-js"><span class="hljs-comment">//main.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>
<span class="hljs-comment">//Importing the store we created above</span>
<span class="hljs-keyword">import</span> { store } <span class="hljs-keyword">from</span> <span class="hljs-string">"./redux/store"</span>
<span class="hljs-comment">//importing the provider from react-redux  </span>
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>

ReactDOM.render(
    <span class="hljs-comment">//This makes the store accessible to the App that is passing it as a prop</span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
)
</code></pre>
<h3 id="heading-how-to-create-a-redux-state-slice">How to create a Redux state slice</h3>
<p>After the store has been created, create a file <code>src/redux/countslice.jsx</code>. Then import <code>createSlice</code> from <code>@redux/toolkit</code>.</p>
<p>A Redux slice is a concept introduced by Redux Toolkit that represents a self-contained piece of the Redux store that includes a reducer function, initial state, and action creators.</p>
<p>Slices provide a way to organize and modularize Redux code, making it easier to manage and maintain as your application grows. You can think of slices as mini-Redux stores that handle a specific piece of state within your application.</p>
<p>Creating a slice requires three things:</p>
<ul>
<li>Name, which is usually set to be a string. </li>
<li>Initial State Value.</li>
<li>Reducer, which contains actions that define how the state can be updated.</li>
</ul>
<p>Creating a state slice creates a more modular and maintainable architecture for your application, making it easier to reason about and update as your application grows.</p>
<p>By organizing your Redux code into slices, you can create a more modular and maintainable architecture for your application, making it easier to reason about and update as your application grows.</p>
<p>After you create the slice, the reducers and the Redux actions inside the reducers are exported differently. This is because the slice created will need to be exported before it can be used inside the store. </p>
<p>By exporting the reducer from the slice, you can easily use it to configure your Redux store. It also makes it easy to test the reducer in isolation, without needing to set up a full Redux store. This can be useful for unit testing and ensuring that the reducer behaves as expected for each action it handles.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>

<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> counterSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'counter'</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">increment</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      state.count += <span class="hljs-number">1</span>
    },
    <span class="hljs-attr">decrement</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      state.count -= <span class="hljs-number">1</span>
    },
    <span class="hljs-attr">incrementByAmount</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.count += action.payload
    },
  },
})

<span class="hljs-comment">// Action creators are generated for each case reducer function</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { increment, decrement, incrementByAmount } = counterSlice.actions

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> counterSlice.reducer
</code></pre>
<h3 id="heading-how-to-add-the-slice-to-the-store">How to add the slice to the store</h3>
<p>The <code>Reducer</code> exported from the slice is imported and added to the store you created earlier. This allows you to complete the configuration of the store.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//store.jsx</span>
<span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>
<span class="hljs-comment">//Importing the reducer from countSlice</span>
<span class="hljs-keyword">import</span> counterReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./countslice"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">counter</span>: counterReducer,
  },
})
</code></pre>
<h3 id="heading-how-to-use-the-state-and-actions-in-your-react-components">How to use the state and actions in your React components.</h3>
<p>Up until now, you've just been going through the initial set up for Redux Toolkit, setting up the store and creating the reducer. Now you need to start making use of the state and actions in your app to achieve the desired functionality.</p>
<p>You will be using two hooks: <code>useDispatch</code> and <code>useSelector</code> . Data are being read from the store through the <code>useSelector</code> hook while the actions are being dispatched using the <code>useDispatch</code> hook. </p>
<p>The corresponding actions (increment, decrement, and incrementByAmount) are being imported from the <code>countSlice.jsx</code> file to be used by the <code>dispatch</code>.</p>
<p>Take a look at the code below where the state is set to a variable <code>count</code> using the <code>useSelector</code> hook and the actions is set to a variable <code>dispatch</code> using the <code>useDispatch</code>. There are three buttons: the <code>increase</code> button, <code>decrease</code> button, and <code>increaseByAmount</code> button. An <code>onClick</code> event was placed on each button which run the various action.</p>
<p>When these buttons are clicked, two things happens:</p>
<ul>
<li>The Redux action is dispatched to the store.</li>
<li>The slice reducer will see the action and then update the state.</li>
</ul>
<p>Here's the code that does all that:</p>
<pre><code class="lang-js"><span class="hljs-comment">//App.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>
<span class="hljs-keyword">import</span> { decrement, increment, incrementByAmount } <span class="hljs-keyword">from</span> <span class="hljs-string">"./redux/countslice"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> count = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.counter.count)
  <span class="hljs-keyword">const</span> dispatch = useDispatch()

  <span class="hljs-keyword">return</span> (

      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'App'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>The count is {count}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"button"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(increment())}
        &gt;
          Increase
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(decrement())}
        &gt;
          Decrease
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=&gt;</span>dispatch(incrementByAmount(10))} &gt; Increase by 10<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

  )
}
</code></pre>
<h3 id="heading-the-result">The Result</h3>
<p>This is exactly what you should get when you run your code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Redux-toolkit-GIF.gif" alt="Image" width="600" height="400" loading="lazy">
<em>App Showing the function of Redux Toolkit</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This tutorial walked you through how you can make use of Redux toolkit in handling your state in React. You learned how to create a store using various hooks such as the  useSelector and useDispatch hook to read data from the store. </p>
<p>At this point you should be confident enough to use the Redux toolkit for managing state in your React app. </p>
<p>Let’s connect on <a target="_blank" href="https://twitter.com/Quincyoghenex">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/quincy-oghenetejiri">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
