<?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[ Redux - 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[ Redux - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 10:29:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/redux/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Learn Redux and Redux Toolkit for State Management ]]>
                </title>
                <description>
                    <![CDATA[ State management is one of the most important aspects of building scalable and efficient React applications. Whether you're managing user interactions, API data, or application-wide settings, having a robust tool for handling state can save time and ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-redux-and-redux-toolkit-for-state-management/</link>
                <guid isPermaLink="false">673e03874ee4d6be53b9fe65</guid>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ redux-toolkit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 20 Nov 2024 15:43:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732117361940/ab139527-5428-4787-bd2c-c2f1336ece8a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is one of the most important aspects of building scalable and efficient React applications. Whether you're managing user interactions, API data, or application-wide settings, having a robust tool for handling state can save time and prevent bugs. That's where Redux, a popular state management library, and its modern sibling, Redux Toolkit, shine. These tools provide a structured and predictable way to manage state in your applications, making them an essential skill for React developers.</p>
<p>We just published a course on the freeCodeCamp.org YouTube channel that will teach you all about Redux and Redux Toolkit. Created by Khaiser Khanam, this comprehensive course takes you from foundational concepts to advanced state management patterns. Whether you're a beginner eager to understand how Redux works or an experienced developer looking to master Redux Toolkit and industry best practices, this course has something for everyone. You'll build real-world applications and learn to avoid common pitfalls while integrating Redux into React projects.</p>
<h3 id="heading-what-youll-learn-in-this-course">What You’ll Learn in This Course</h3>
<h4 id="heading-part-1-redux-fundamentals"><strong>Part 1: Redux Fundamentals</strong></h4>
<p>The course begins with an in-depth exploration of Redux's core concepts, including actions, reducers, and the store. Through clear analogies and visualizations, you’ll learn:</p>
<ul>
<li><p>Why Redux is useful and when it might not be the right choice.</p>
</li>
<li><p>The three principles of Redux and how they guide state management.</p>
</li>
<li><p>Middleware, including how to use Thunk for handling async logic.</p>
</li>
<li><p>Setting up React-Redux and leveraging hooks like <code>useSelector</code> and <code>useDispatch</code> to connect your React components to Redux.</p>
</li>
<li><p>Building a professional folder structure for your Redux projects.</p>
</li>
</ul>
<p>The first half of the course also dives into practical examples, such as creating a "burger application," combining reducers, implementing logger middleware, and integrating the Redux DevTools extension. By the end of this section, you’ll have a solid foundation to use Redux confidently in your projects.</p>
<h4 id="heading-part-2-redux-toolkit-essentials"><strong>Part 2: Redux Toolkit Essentials</strong></h4>
<p>In the second part, you’ll dive into Redux Toolkit, a modern library that simplifies working with Redux by reducing boilerplate code and improving developer experience. Topics include:</p>
<ul>
<li><p>The <code>createSlice</code> method and its role in simplifying reducer and action creation.</p>
</li>
<li><p>Advanced patterns like extra reducers and the <code>createAsyncThunk</code> function for handling async actions.</p>
</li>
<li><p>Setting up projects with Vite, and building features like a pizza-and-burger ordering application.</p>
</li>
<li><p>Utilizing the Immer library for immutable state updates, and exploring how Redux Toolkit integrates seamlessly with React DevTools.</p>
</li>
</ul>
<p>This section also covers best practices, common beginner mistakes, and Redux Toolkit interview questions to help you prepare for real-world use cases and technical evaluations.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Redux and Redux Toolkit are must-know tools for React developers aiming to build professional-grade applications. This course provides a step-by-step approach, ensuring that even complex topics like middleware, async actions, and advanced state patterns are accessible. Plus, you’ll work on real-world projects, reinforcing the concepts through practical application.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/SlC8941Wwrk">the freeCodeCamp.org YouTube channel</a> (8-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/SlC8941Wwrk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </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[ 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[ 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[ 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[ React Unit Test Handbook + Redux Testing Toolkit ]]>
                </title>
                <description>
                    <![CDATA[ In this step-by-step tutorial, you'll learn how to easily start with Unit Tests in React. You'll learn how to write tests for Redux states as well as fundamental Redux slice tests using the React Testing Library and Jest. 🔐 Here's What We'll Cover ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-unit-tests-in-react-redux/</link>
                <guid isPermaLink="false">66bb8f42fce17a7d998852db</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matthes B. ]]>
                </dc:creator>
                <pubDate>Wed, 09 Nov 2022 15:32:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/pexels-scott-webb-1527893.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this step-by-step tutorial, you'll learn how to easily start with Unit Tests in React. You'll learn how to write tests for Redux states as well as fundamental Redux slice tests using the React Testing Library and Jest.</p>
<h2 id="heading-heres-what-well-cover"><strong>🔐 Here's What We'll Cover</strong></h2>
<ul>
<li>You'll see how easy it is to set up your first unit tests in React.</li>
<li>You'll improve your general React knowledge.</li>
<li>You'll get the hang of why Test Driven Development (TDD) is helpful for your coding workflow.</li>
</ul>
<h2 id="heading-prerequisites"><strong>📝</strong> Prerequisites</h2>
<ul>
<li>You should be familiar with the basic React workflow structure (including functional components and hooks).</li>
<li>You should have a basic knowledge of Redux (I'm using Redux Toolkit for this guide).</li>
<li>You don't need any prior knowledge about testing.</li>
<li>I'm using the <code>npm</code> installation approach, not the <code>yarn</code> one.</li>
</ul>
<h2 id="heading-the-objective"><strong>🎯</strong> The Objective</h2>
<p>While learning advanced concepts of React, you'll probably stumble across the topic of testing. Being able to work with automatic tests is also quite handy for any upcoming frontend developers. </p>
<p>However, as I myself was learning React, I had a hard time finding information about how to implement tests for libraries like Redux (even though it's a library I work with all the time). </p>
<p>Beyond that, I found that doing any component testing in React is basically unfeasible when you don't know how to work with the Redux library.</p>
<p>So I took some time to read the Redux documentation and went back and forth with it a bit. Then I decided to write a practical starter guide for unit testing in React, including Redux, to share what I learned. </p>
<p>Since I would like to take a modern approach, I'm also going to use the Redux Toolkit. We'll cover the Redux implementation in this guide.</p>
<h3 id="heading-what-well-cover">What we'll cover:</h3>
<p>To start off, I will provide some general information about tests before I directly go into creating the first general unit tests. </p>
<p>Next I'll give a quick overview of how to implement some Redux Toolkit logic. </p>
<p>Then we will work on some unit tests within an application which uses Redux Toolkit. For this step we will adjust our previously created tests to the new Redux environment.</p>
<p>This is a step-by-step guide. If you are new to tests, I recommend following this guide in order from top to bottom.</p>
<p>I have also created a <a target="_blank" href="https://github.com/Matthes-Baer/unit-test-redux-article-app">public GitHub repository</a> for this guide with some commentary. You can use that if you want to look something up without scrolling through this guide in its full length again.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#what-different-kinds-of-tests-are-there">What Different Kinds of Tests Are There?</a></li>
<li><a class="post-section-overview" href="#how-to-set-up-your-react-testing-environment">How to Set Up Your React Testing Environment</a></li>
<li><a class="post-section-overview" href="#heading-check-out-your-created-react-application">Check Out Your Created React Application</a></li>
<li><a class="post-section-overview" href="#how-to-create-your-first-unit-test">How to Create Your First Unit Test</a></li>
<li><a class="post-section-overview" href="#how-to-create-a-failing-test-on-purpose">How to Create a Failing Test on Purpose</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-some-additional-tests">How to Create Some Additional Tests</a></li>
<li><a class="post-section-overview" href="#heading-how-to-perform-testing-with-the-react-redux-toolkit">How to Perform Testing with the React Redux Toolkit</a></li>
<li><a class="post-section-overview" href="#heading-outlook-for-advanced-testing">Outlook for Advanced Testing</a></li>
</ol>
<h2 id="heading-what-different-kinds-of-tests-are-there">📋 What Different Kinds of Tests Are There?</h2>
<p>This quick guide won't provide you with detailed theoretical knowledge about all the <a target="_blank" href="https://www.freecodecamp.org/news/types-of-software-testing/">different kinds of testing out there</a>. At this point, you should just understand that there are generally three kinds of tests:</p>
<ul>
<li>Unit Tests</li>
<li>Integration Tests</li>
<li>End-To-End Tests</li>
</ul>
<p>To put it in simple words: You can see these three types of tests as generally increasing in their complexity. </p>
<p>While <a target="_blank" href="https://www.freecodecamp.org/news/unit-tests-explained/">unit tests</a> cover single functions and components, integration tests typically focus on multiple functions and their connections to each other. <a target="_blank" href="https://www.freecodecamp.org/news/end-to-end-testing-tutorial/">End-to-end tests</a> are even more complex and give insights about multiple function and component structures. </p>
<p>There are other test concepts, but these three are the most important ones for web developers, for example.</p>
<p>Again, this is really put in simple words. But in this case it's sufficient to know that unit tests are basically the least complex tests out of these three. </p>
<p>It's also quite easy to work with unit tests as soon as you have a basic understanding of how testing in general works.</p>
<p>I would also like to quickly emphasize that there are mainly two ways of testing your application.</p>
<ul>
<li>Manual Testing</li>
<li>Automatic Testing</li>
</ul>
<p>Manual Testing is pretty much what you probably already do for all of your application which you create. When manually testing your application, you basically start your React application with <code>npm run start</code> and actually click on buttons to check if the corresponding function works.</p>
<p>Automatic Tests, on the other hand, are pretty much functions you create which automatically check your application to see if the respective steps work that you defined within these tests. This automatic kind of testing is extremely important for larger projects. </p>
<p>With this automatic approach, it's also way easier to scale your tests. In the end, you have a lot of tests which automatically test your whole application in a relatively short amount of time. These test can help you spot any potential errors which might have occurred during development. This would take much more time if you were to go back constantly to manually test your application.</p>
<p>Being able to work with automatic tests is also typically a big plus for your résumé as a frontend developer.</p>
<h2 id="heading-how-to-set-up-your-react-testing-environment">🔧 How to Set Up Your React Testing Environment</h2>
<p>In order to get a practical start, we are going to directly dive into our React application. </p>
<p>You will see that the setup of a testing environment is relatively easy in React – or, to be more precise, React does it all for you during the regular install setup.</p>
<p>Therefore, I'm creating a React application with the following line:</p>
<p><code>npx create-react-app &lt;name of your application&gt;</code></p>
<p>After this step, we need everything that should be added for using Redux in our React application:</p>
<ul>
<li><strong>React Redux:</strong> <code>npm install react-redux</code> (provides some mandatory hooks, for example)</li>
<li><strong>React Redux Toolkit:</strong> <code>npm install @reduxjs/toolkit</code> (provides logic for creating a store or slices, for example)</li>
</ul>
<p>It's worth mentioning that there also is the <strong>Redux core</strong> (<code>npm install redux</code>). But this is already part of the React Redux Toolkit installation, so we don't have to install it here too. </p>
<p>If you wanted to use React without the React Redux Toolkit, then you would have to separately reach out to the Redux core installation.</p>
<p>You can also create a new React application from scratch with <code>npx create-react-app my-app --template redux</code> which includes the React Redux Toolkit, the React core, React Redux, as well as a template from the React Redux Toolkit. </p>
<p>Choose this approach if you don't have any existing React applications, since it's probably more convenient.</p>
<p>Under the hood, you now have an application that uses the <strong>React Testing library</strong> combined with <strong>Jest</strong> (a testing framework). Together, they have pretty much everything that you will need for testing your React application. </p>
<p>You don't have to install anything else for this purpose. These tools come out of the box with a standard React installation.</p>
<h2 id="heading-check-out-your-created-react-application">🔎 Check Out Your Created React Application</h2>
<p>As you go into your newly created React application, you will find the folder and file structure you are likely familiar with. Besides others, there is the <code>App.js</code> file, which is created like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">'./logo.svg'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</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">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          Edit <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>src/App.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> and save to reload.
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"App-link"</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://reactjs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
          <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>
        &gt;</span>
          Learn React
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</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">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Within the <code>src</code> folder, you also have the file <code>App.test.js</code>. This file is actually a first test that came out of the box with React installation. This file is structured like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { render, screen } <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>;

test(<span class="hljs-string">'renders learn react link'</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> linkElement = screen.getByText(<span class="hljs-regexp">/learn react/i</span>);
  expect(linkElement).toBeInTheDocument();
});
</code></pre>
<p>Even without fully understanding what <code>render</code> or <code>screen</code> is, for example, we can see that something is going on with our <code>App</code> component in there. In fact, this is a unit test that is focusing on a specific part of the <code>App</code> component.</p>
<p>While this first template for a test is a handy representation of what a test looks like, I would like to create a test file from scratch.</p>
<p>Generally speaking, tests are separated into different test suites. These test suites are typically a group of tests that focus on the same component, for example. Tests within the same test suite basically have the same superordinate topic.</p>
<p>To check this, try to enter <code>npm run test</code> in your terminal when you are within your React application. </p>
<p>It could say something like "There are no new tests or changes since the last commit" – in this case, just enter <code>a</code> in the terminal to run all tests regardless.</p>
<p>In the end, you should be able to see this within the terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-124.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of <code>npm run test</code></em></p>
<p>At the top, you can see that the <code>App.test.js</code> file passed. Basically, all tests within this file were successful. </p>
<p>Below that, you can see <code>renders learn react link</code>: This is the description for this particular test, which we can define individually. We will get back to this later.</p>
<p>Further down, we can finally see the test suites and tests. As you can see, we have one test suite and one test. To be more precise, we have one test suite that includes this one test. </p>
<p>Later on, you will recognize that we will use like 1-3 test suites while there will be around 5+ tests, for example. Again, test suites basically provide a structure that groups single tests together.</p>
<p>The stuff with the snapshots is not important for your specific case.</p>
<p><a target="_blank" href="https://jestjs.io/docs/snapshot-testing">Snapshots</a> are an advanced concept for testing. So a reference snapshot (like an image that was taken) is being compared with the version after some actions took place. This can help to check whether the UI stays the same after some actions or if some changes happened all of a sudden.</p>
<p>I won't focus on testing with snapshots in this article. This is a topic that you might want to look up after understanding some unit testing basics.</p>
<h2 id="heading-how-to-create-your-first-unit-test">🔨 How to Create Your First Unit Test</h2>
<p>Now that we've looked at a unit test, lets dive into the first test which we'll build from scratch on our own.</p>
<p>For that, I would like to create a new folder called <code>__tests__</code>. This is common when you are working with tests or checking out other applications. </p>
<p>I'm also dragging the already-available <code>App.test.js</code> file into this folder. This doesn't change anything about the result.</p>
<p>Our folder structure now looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-125.png" alt="Image" width="600" height="400" loading="lazy">
<em>general folder structure with <code>__tests__</code></em></p>
<p>Within <code>__tests__</code>, we create the file <code>myFirstTesting.test.js</code>. We need this file structure of <code>&lt;test name&gt;.test.js</code>. You can also create a test file with <code>&lt;test name&gt;.spec.js</code> – both approaches will work the same.</p>
<p>Our first step is to import the <code>App.js</code> component: <code>import App from "../App";</code>.</p>
<p>To create our first test, we have to make use of the <code>test()</code> function. You could also use <code>it()</code>. Both will achieve the same result. </p>
<p>The first parameter of this function has to be a string, which describes what we are going to test (remember the stuff with "renders learn react link" within the test file we viewed?). This is going to help you have a more precise overview after running all the tests. </p>
<p>In this case, I will use the description <code>"renders logo in App component"</code>. The second parameter is another function for which we are using an anonymous arrow function. Our <code>myFirstTesting.test.js</code> file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"../App"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {

})
</code></pre>
<p>Even though there is not much going on, let's try entering <code>npm run test</code> again. We will find the following result in our terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-126.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Therefore, we now have two test files, resulting in two test suites and two tests.</p>
<p>Now we would actually like to test something. Since we added the description <code>"renders logo in App component"</code>, we are going to test exactly that. </p>
<p>In order to do that, we need the <code>render()</code> function, which we'll use whenever we actually want to render a component from our application.</p>
<p>In order to add the <code>render()</code> function, we have to import it from the React Testing library, which is already part of our React application without any other installations. </p>
<p>While we're at this step of importing, let's also import <code>screen</code> (also part of the React Testing library). It provides access to different functions that will look through the current screen after something gets rendered and find specific elements, for example.</p>
<p>After adding these two imports, our <code>myFirstTesting.test.js</code> file now looks like this:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {

})
</code></pre>
<p>Now that we have all that, let's actually start working on our test.</p>
<p>First of all, we need to render our component. Remember that tests are self-contained and don't know that we have an <code>App.js</code> with the corresponding content in our React application. We have to individually tell the specific test that a component exists by rendering it with <code>render()</code> at the top of the test. This is going to look like this: <code>render(&lt;App /&gt;);</code>.</p>
<p>Now that we have rendered the <code>App.js</code> component in this test, we should try to check if a specific content part can be found by the test. This way, we can actually test if <code>App.js</code> was rendered like it was supposed to be. </p>
<p>Assuming something went wrong, we would not be able to find the React logo, for example, which is currently part of the <code>App.js</code> component.</p>
<p>So we will try to find this logo, which is an <code>img</code> element. To do this, we can make use of the <code>getByAltText()</code> function that finds an element by its specific <code>alt</code> attribute, which is commonly utilized for images. We have access to this function with <code>screen</code> that we imported earlier. </p>
<p>We now have this expression: <code>screen.getByAltText("logo")</code>. So the test looks at the screen where we rendered the <code>App.js</code> component beforehand, and then gets an element, which has an <code>alt</code> attribute of <code>"logo"</code>. We will connect all this to a variable. </p>
<p>Our test file now looks like this:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
})
</code></pre>
<p>There are a bunch of different functions like <code>getByAltText()</code> that you can use to look for elements with a specific text content, a specific role like a button, or even with a test id that you can add to the actual element.</p>
<p>You also have the opportunity to look for multiple elements. Besides that, you don't have to use a string as parameter. A regular expression with <code>/logo/i</code> is also feasible, for example. We will use different ways to find elements throughout this starter guide.</p>
<p>For the last step, we have to utilize <code>expect()</code>, which we use to see what behavior we can expect. In this case, we expect that our <code>image</code> variable is part of the component and therefore exists. </p>
<p>For this approach, our file would look like this:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
  expect(image).toBeInTheDocument();
})
</code></pre>
<h2 id="heading-how-to-create-a-failing-test-on-purpose">❗ How to Create a Failing Test on Purpose</h2>
<p>If we now run our tests with <code>npm run test</code>, everything will pass. Now, let's try to reverse this logic so that we actually create a failing test. This way, we can check if this test actually has some impact or not. </p>
<p>To do this, we can go into our <code>App.js</code> file and change the <code>alt</code> attribute for the logo image. If you change it to <code>alt="loo"</code>, the test will fail and it'll give you some information.</p>
<p>In our case, though, I would like to change something on the test itself to make it fail and show you another expression that is handy to know. Instead of <code>expect(image).toBeInTheDocument();</code> we can also type <code>expect(image).not.toBeInTheDocument();</code>. So here we added a <code>not</code>. This basically reversed the logic, and now the test expects that no such image element exists.</p>
<p>If we now try to run the test, we will find the following error message in our terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-127.png" alt="Image" width="600" height="400" loading="lazy">
<em>The error message we get</em></p>
<p>You can see that the test expected that there was no such element as <code>image</code>. However, it found something and therefore answered with an error message.</p>
<p>You don't have to make all your tests purposely fail to check if they work or not. I just wanted to show you what an actual failing test would look like.</p>
<h2 id="heading-how-to-create-some-additional-tests">✏️ How to Create Some Additional Tests</h2>
<p>Now we have finished with our first test and have some basic knowledge about what to expect when working with unit tests. Next, we will check out some other test examples.</p>
<p>In order to create a more realistic scenario, I will add one additional component, which we'll insert into the <code>App.js</code> component.</p>
<p>For this step, first we create a folder called <code>components</code> in our <code>src</code> folder. This is not a must, but it is common to structure your files like that.</p>
<p>Within the <code>components</code> folder, we create <code>List.js</code>. Our folder structure now looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-155.png" alt="Image" width="600" height="400" loading="lazy">
<em>current folder structure</em></p>
<p>Now, let's try to follow more of a test driven development (TDD) workflow, which is quite modern. I'm not necessarily sayint that this is always recommended. But a TDD approach is considered best practice by more and more people nowadays. </p>
<p>Of course, in this tutorial we'lre "only" talking about unit tests and not integration or end-to-end tests, but the general TDD workflow is similar for all three test categories.</p>
<p>So using this test driven development approach, we basically add tests and work on our application simultaneously. </p>
<p>To be more precise, we even create tests for single components and function parts before you even implement this tested logic in your application. </p>
<p>So there is a lot of going back and forth instead of creating all the tests at once at the end.</p>
<h3 id="heading-how-to-start-the-setup-for-listjs">How to Start the Setup for <code>List.js</code></h3>
<p>In our example, we have added the <code>List.js</code> component. Within this component, I would like to add a list with a button. When a user clicks on the button, it adds something to the list (an object with multiple keys and values).</p>
<p>In order to have some sort of frame, I will first add some <code>div</code> elements and similar stuff to our <code>List.js</code> component before we dive into the actual logic.</p>
<p>The <code>List.js</code> component now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> List = <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>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>This is the first list entry<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">button</span>&gt;</span>This button can add a new entry to the list<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> List;
</code></pre>
<p>I also added the <code>List.js</code> component as a child to <code>App.js</code> (below all the other stuff in <code>App.js</code>) so it will be visible without changing anything else.</p>
<p>The result looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>How it looks</em></p>
<p>This won't win you any style competitions but it's sufficient for our case.</p>
<h3 id="heading-setup-for-the-test-for-listjs">Setup for the test for <code>List.js</code></h3>
<p>Since we want to test while we are working on our component, I will now jump directly to the testing part even if nothing really happened in our <code>List.js</code> component in terms of click functions, for example.</p>
<p>We could create a new test file, but I would like to show you a new function we can use for our test suites specifically. This function is called <code>describe()</code> and can be handy for further structuring our tests.</p>
<p>To use <code>describe()</code>, we jump to <code>myFirstTesting.test.js</code> within <code>__tests__</code>. Right now, this file basically serves as one test suite for the test we specifically created for the <code>App.js</code> component. But I would like to have two test suites within this test file: one for the <code>App.js</code> tests and one for the <code>List.js</code> tests.</p>
<p>For this step, I'm using the <code>describe()</code> function, which basically works like the <code>test()</code> function in terms of parameters. </p>
<p>The first parameter will be a string, describing the respective test suite. The second parameter is a function, which then includes our <code>test()</code> functions with their stuff.</p>
<p>It will look like this in our case:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>Before we jump into this new test, I would actually like to add something for the <code>App.js</code> testing. Since we have this <code>describe()</code> block, we could just add a new <code>test()</code> function – and this is what I'm going to do.</p>
<p>See the following newly added test described with <code>"renders List.js component in App.js"</code>:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });

   test(<span class="hljs-string">"renders List.js component in App.js"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>So I'm rendering the <code>App.js</code> component and looking for text via a regular expression, which is part of the <code>List.js</code> component. This test can basically be understood as a render test for <code>List.js</code>. If <code>List.js</code> had not been able to be rendered within <code>App.js</code>, this test would not pass.</p>
<p>If you are confused that this works without separately using <code>render()</code> on the <code>List.js</code> component, remember that <code>List.js</code> is part of <code>App.js</code> and everything inside <code>App.js</code> will be rendered under typical conditions. If you tried to look for a text phrase that doesn't exist in <code>List.js</code>, this new test would fail. Right now, in our case, it passes.</p>
<p>I would also like to emphasize that you can have multiple <code>expect()</code> functions within the same test. Therefore, we also could have structured this new test like this:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);

    expect(image).toBeInTheDocument();
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"example"</span>, <span class="hljs-function">() =&gt;</span> {});
});
</code></pre>
<p>This would also work perfectly fine in our case. And this can be handy in situations where you test for some small elements which are directly connected to each other and have the same requirements to be rendered. </p>
<p>But keep in mind that in our case, we should have adjusted the description for this test. That's because <code>"renders logo in App component"</code> is not correct anymore if we are testing more than that in this test. So let's head back to the structure with two separate tests for now. But have in mind that you are able to work like this.</p>
<h3 id="heading-back-to-the-test-for-listjs">Back to the test for <code>List.js</code></h3>
<p>Now I would like to work with the second <code>describe()</code> block that we created a few moments ago, where we want to work with tests specifically for the <code>List.js</code> component.</p>
<p>Since we are aiming for a test-driven development approach, we should think about what we are going to build, write a test, and then implement that logic in our component.</p>
<p>We want to create a simple list in our <code>List.js</code> component. So there will be an array, which we will go through with <code>map()</code>. </p>
<p>For this approach, we will utilize the <code>useState()</code> hook so we have a state that can dynamically adjust (the array of list items). Our first test will be to check if the length of this array in its initial state is equal to <code>1</code>.</p>
<p>To find the items within this state, we will make use of the <code>getAllByTestId()</code> method, which allows us to search for specific elements we marked with a <code>data-testid</code> in the frontend. </p>
<p>The test with the description <code>"renders initial state of listData state"</code> that I created is now included:</p>
<pre><code class="lang-javascript"><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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);

    expect(image).toBeInTheDocument();
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
   test(<span class="hljs-string">"renders initial state of listData state"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">1</span>);
  });
});
</code></pre>
<p>Right now this test will fail, of course, because we haven't added any of this logic to the component yet.</p>
<p>So I adjusted the <code>List.js</code> component. It now looks like this:</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">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> initialState = [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ];
  <span class="hljs-keyword">const</span> [listData, setListData] = useState(initialState);

  <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">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listData.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <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">button</span>&gt;</span>This button can add a new entry to the list<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> List;
</code></pre>
<p>Newly added was the <code>listData</code> state array via a <code>useState()</code> hook as well as an initialState, which I initialized with one object at the very top. I also made use of the <code>map()</code> function to go through this <code>listData</code> to create a list. </p>
<p>For each <code>&lt;li&gt;</code> element, I'm adding a key and a <code>data-testid</code>. This <code>data-testid</code> is the id we need for our test to find the respective elements.</p>
<p>On our actual application, we can see the <code>listItem.description</code> for this initial state:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-165.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So by manually testing (actually looking at our application in the browser), we can see that this should work. If we now run our tests, we will also see that the test we created passed.</p>
<h3 id="heading-how-to-add-an-object-to-the-state">How to add an object to the state</h3>
<p>Now let's test something more exciting: the logic to add a new object to this <code>listData</code> state. Again, we will start by working on our test first before actually implementing the required logic within the React component.</p>
<p>With this newly added test described by <code>"adds a new data entry to listData after button click"</code>, our test file now looks like this:</p>
<pre><code class="lang-javascript"><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> List <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/List"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;

<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/user-event"</span>;

describe(<span class="hljs-string">"App.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders logo in App component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> image = screen.getByAltText(<span class="hljs-string">"logo"</span>);
    expect(image).toBeInTheDocument();
  });

  test(<span class="hljs-string">"renders List.js component in App.js"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> textInListJS = screen.getByText(<span class="hljs-regexp">/This is a list/i</span>);
    expect(textInListJS).toBeInTheDocument();
  });
});

describe(<span class="hljs-string">"List.js component"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"renders initial state of listData state"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">1</span>);
  });

  test(<span class="hljs-string">"adds a new data entry to listData after button click"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">List</span> /&gt;</span></span>);
    <span class="hljs-keyword">let</span> listItems = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    <span class="hljs-keyword">const</span> button = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/This button can add a new entry to the list/i</span>,
    });

    expect(list.length).toEqual(<span class="hljs-number">1</span>);
    userEvent.click(button);
    list = screen.getAllByTestId(<span class="hljs-string">"list-item"</span>);
    expect(list.length).toEqual(<span class="hljs-number">2</span>);
  });
});
</code></pre>
<p>At the bottom, you can see this test. Therefore, we are first rendering the <code>List.js</code> component before looking for all available list items we assigned a test id to. You will see exactly where we put the test id in a few moments.</p>
<p>We also have to look for the button that we want to test to see if clicking on it adds something to the list. We do this with <code>getByRole()</code> which expects a role like <code>"button"</code> or <code>"table"</code> as a first parameter, for example (there are a bunch of different roles you can target). The second parameter is optional and is an object that can receive a value for the <code>name</code> key.</p>
<p><code>name</code> is pretty much the text content we have specifically for the button in this case. This optional second parameter is handy when you have multiple elements of type <code>"button"</code> in your component and want to get a specific button out of these.</p>
<p>After getting the <code>listItems</code> as well as the <code>button</code>, we start off with a first <code>expect()</code> to basically test the initial state. In this initial state, we expect to have only one list item.</p>
<p>Then, with the help of <code>userEvent</code>, we are going to click on the button. You could also use <code>fireEvent</code> for this situation (<code>userEvent</code> is still pretty new compared to the <code>fireEvent</code> approach). Both will work, and both are helpful for any action where you want to interact with specific elements. In this case, I want to simulate clicking on a button.</p>
<p>Tests generally follow a "arrange -&gt; act -&gt; assert" pattern that you can follow to structure them. Within the "arrange" part, you initialize and get all required elements. With the "act" part, you would simulate a mouse click (as in our case), for example. With "assert," you are checking if it all behaves like you expected it to.</p>
<p>In another case, you could simulate changing the value of an input field with <code>fireEvent.change(inputField, { target: { value: someValueVariable } })</code>, for example. Maybe you want to focus an input field or even drag an element - such actions can be simulated via <code>fireEvent</code> and <code>userEvent</code>.</p>
<p>After the button click, it again looked for all <code>listItems</code> since the current value of this variable would still be <code>1</code> from the previous initialization. As soon as this step is completed, it uses another <code>expect()</code> function to check if the length of the <code>listItems</code> array is now equal to <code>2</code> and not <code>1</code>.</p>
<p>Now that we have our test logic, let's jump back to the <code>List.js</code> component and implement the corresponding logic:</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">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> initialState = [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ];
  <span class="hljs-keyword">const</span> [listData, setListData] = useState(initialState);

  <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">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listData.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <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">button</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span>
          setListData([
            ...listData,
            { id: 999, description: "999", significance: 100 },
          ])
        }
      &gt;
        This button can add a new entry to the list
      <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> List;
</code></pre>
<p>The only part that changed is the button at the bottom of this file. So I added a function that gets invoked when clicking on this button. The function then adjusts the current state of <code>listData</code> which is responsible for rendering our list. I copied the current state with a spread operator and then added another hard-coded object as the new entry for this list. </p>
<p>Of course, there are more creative ways to fill in the values for the <code>id</code>, <code>description</code>, and <code>significance</code> keys.</p>
<p>I would also like to emphasize that you have the opportunity to create a separate function outside of the <code>return()</code> and access this function like this: <code>onClick={separateFunctionToAddObjectToState}</code> on the same button element. This would also work without having to render something additional within the test.</p>
<p>If we now run our test, we will see that it passes. If you try to still expect a length of <code>1</code> after clicking on the button, the test will fail like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-192.png" alt="Image" width="600" height="400" loading="lazy">
<em>error alert for length of 1</em></p>
<p>So it actually does what it is supposed to do.</p>
<h2 id="heading-setup-for-redux">🔧 Setup for Redux</h2>
<p>After working with local states via the <code>useState()</code> hook, I would like to work on the same files and adjust them for Redux (or the Redux Toolkit, to be precise). </p>
<p>I'm not going to dive deep into what Redux actually is and what every term like <code>action</code>, <code>store</code>, or <code>reducer</code> means in detail – since this would be worthy of a whole new guide. If you want that, you can <a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners/">read this guide to Redux basics</a>.</p>
<p>Instead, I will give just a quick rundown and show which files I'm adding and editing. Then I'll talk about how to handle the <code>render()</code> method, including the Redux store provider, which can cause a lot of frustration when testing if you don't know about it.</p>
<h3 id="heading-overall-folder-structure">Overall folder structure:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-14.png" alt="Image" width="600" height="400" loading="lazy">
<em>current overall folder structure with the React Redux Toolkit</em></p>
<p>You can see that I added an <code>app</code> (for the store) as well as a <code>features</code> (for the slice) folder.</p>
<h3 id="heading-updated-indexjs-file">Updated <code>index.js</code> file:</h3>
<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/client"</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-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">"./reportWebVitals"</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">"./app/store"</span>;

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.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>
<p>You can see that I added a <code>provider</code> and wrapped it around the application so we have access to the store from anywhere.</p>
<h3 id="heading-created-storejs-file">Created <code>store.js</code> file:</h3>
<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> { ListSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">listReducers</span>: listSlice.reducer,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>In this file, we have created the required store for the Redux implementation.</p>
<h3 id="heading-created-listslicejs-file-in-features-folder">Created <code>ListSlice.js</code> file in <code>features</code> folder:</h3>
<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">export</span> <span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">value</span>: [
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is something"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">7</span>,
    },
  ],
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ListSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"listReducers"</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {},
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { } = ListSlice.actions;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ListSlice.reducer;
</code></pre>
<p>Here we have created the slice that we added to the store. Notice that I haven't added any reducer yet. This slice just contains the current corresponding state.</p>
<h3 id="heading-updated-listjs-file-in-components-folder">Updated <code>List.js</code> file in <code>components</code> folder:</h3>
<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">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> listState = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.listReducers.value);
  <span class="hljs-keyword">const</span> dispatch = useDispatch(); <span class="hljs-comment">// not used right now</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">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listState.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <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">button</span>&gt;</span>This button can add a new entry to the list<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> List;
</code></pre>
<p>On the frontend, we swapped the local state (using the useState hook) with the Redux state (using the useSelctor hook). You'll also see that I adjusted the button. There is no click function anymore (we will get back to that later on).</p>
<h2 id="heading-how-to-perform-testing-with-the-react-redux-toolkit">🔎 How to Perform Testing with the React Redux Toolkit</h2>
<p>Now that we have updated and created all the necessary files for the React Redux Toolkit logic, I would like to run a quick test of all the tests we previously created.</p>
<p>The result is that all tests have failed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Keep in mind that I adjusted the button in <code>List.js</code>, for example, so the corresponding test was expected to fail. However, not all tests should have failed.</p>
<p>The test environments are working in their own world. They don't know if you wrap a provider somewhere in <code>index.js</code> and enable Redux logic. So the tests are still trying to make the rendering work without Redux. But our application now depends on Redux to manage our main state.</p>
<p>This means that we have to adjust the <code>render()</code> function so that this function is actually aligned with the Redux logic.</p>
<p>A method to make this work is to introduce a helper function, which we will store in a new folder called <code>utils</code>. The file will be called <code>utils-for-tests.jsx</code>. The content will look like this:</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> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</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> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-comment">// As a basic setup, import your same slice reducers</span>
<span class="hljs-keyword">import</span> { ListSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">renderWithProviders</span>(<span class="hljs-params">
  ui,
  {
    preloadedState = {},
    <span class="hljs-regexp">//</span> Automatically create a store instance if no store was passed in
    store = configureStore({
      reducer: { listReducers: ListSlice.reducer },
      preloadedState,
    }),
    ...renderOptions
  } = {}
</span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Wrapper</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">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>;
  }

  <span class="hljs-comment">// Return an object with the store and all of RTL's query functions</span>
  <span class="hljs-keyword">return</span> { store, ...render(ui, { <span class="hljs-attr">wrapper</span>: Wrapper, ...renderOptions }) };
}
</code></pre>
<p>This code information can be found in the <a target="_blank" href="https://redux.js.org/usage/writing-tests">Redux documentation</a>. You can almost copy and paste it all for your application.</p>
<p>But you have to adjust the slices that are used in there. Since in our application there is only the <code>ListSlice</code> we don't have much to add. Just import that and update the content of the <code>configureStore()</code> function, like we managed it in our <code>store.js</code> file.</p>
<p>This step is necessary to basically mock the entire Redux logic and put it together into one new <code>render()</code> function.</p>
<p>With that, we can import this new function into our test files (<code>App.test.js</code> and <code>myFirstTesting.test.js</code>) and then replace all <code>render()</code> functions with <code>renderWithProviders()</code>. The <code>App.test.js</code> file, for example, now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { screen } <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">import</span> { renderWithProviders } <span class="hljs-keyword">from</span> <span class="hljs-string">"../utils/utils-for-tests"</span>;

test(<span class="hljs-string">"renders learn react link"</span>, <span class="hljs-function">() =&gt;</span> {
  renderWithProviders(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> linkElement = screen.getByText(<span class="hljs-regexp">/learn react/i</span>);
  expect(linkElement).toBeInTheDocument();
});
</code></pre>
<p>There is not much more to do! If we now run our tests again (and comment out this one test, which is going to fail regardless because the button logic is not active anymore), it will work again.</p>
<h3 id="heading-slice-testing">Slice testing</h3>
<p>Another exciting part about testing with Redux is testing the slices. If you created your application with the React Redux Toolkit template, then you will be provided with some corresponding tests.</p>
<p>For our case, I also want to implement a new test file where we will specifically test <code>ListSlice.js</code> and its corresponding Redux logic.</p>
<p>For this slice, we have to import the slice and the corresponding reducers we want to test. To start, I will import the slice and test if it gets initialized with the initialState.</p>
<p>This is actually not the TDD approach since we already manually tested this part. Netherless, I would like to implement an automatic test as well:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ListSlice, { initialState } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

describe(<span class="hljs-string">"tests for ListSlice"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"initialize slice with initialValue"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> listSliceInit = ListSlice(initialState, { <span class="hljs-attr">type</span>: <span class="hljs-string">"unknown"</span> });
    expect(listSliceInit).toBe(initialState);
  });
});
</code></pre>
<p>Notice that I'm using <code>.spec</code> instead of <code>.test</code>. This doesn't matter. You can choose either. In this case, I'm going with <code>.spec</code> to remind you that this is also a viable option.</p>
<p>Also remember that we exported the initialState within our slice (see above). So we are able to import it here.</p>
<p>Other than that, we are already familiar with the <code>describe()</code> environment, which includes one <code>test()</code>. Within this test, I'm initializing a variable <code>listSliceInit</code>, which will hold the value we are receiving after the slice operation took place.</p>
<p>For this operation, we use <code>ListSlice</code> as a function and include the initial state as the first argument (in this case <code>initialState</code>). The second argument will be a reducer in most cases. </p>
<p>But in this case, we don't need to enter a reducer. Instead, we are using an object with <code>type: "unknown"</code>. This is basically telling the function that we don't want to perform any additional operations.</p>
<p>Therefore, <code>listSliceInit</code> should now include our state value, which includes an array with one entry. The corresponding test will pass.</p>
<p>To force a failure, I'm entering <code>expect(listSliceInit).toBe({ value: [] });</code> instead of the previous <code>expect()</code> function. So instead of our <code>initialState</code> we are expecting it to have an empty array. Now our test environment will tell us the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>failing test</em></p>
<p>So it actually tells us what exactly it expected – in this case, it expected the <code>initialState</code>.</p>
<p>Next, I would like to test a reducer. However, we haven't added one yet. So I will adjust <code>ListSlice</code> in the <code>ListSlice.js</code> file like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ListSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"listReducers"</span>,
  initialState,
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">testAddReducer</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.value.push(action.payload);
    },
  },
});
</code></pre>
<p>Thus, I added <code>testAddReducer()</code>, which is responsible for pushing one additional element to the current state value, which it receives via an input from the dispatch (through <code>action.payload</code>).</p>
<p>If we now jump back to the <code>listSlice.spec.js</code> file, I'm adding another unit test:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ListSlice, { initialState, testAddReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

describe(<span class="hljs-string">"tests for ListSlice"</span>, <span class="hljs-function">() =&gt;</span> {
  test(<span class="hljs-string">"initialize slice with initialValue"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> listSliceInit = ListSlice(initialState, { <span class="hljs-attr">type</span>: <span class="hljs-string">"unknown"</span> });
    expect(listSliceInit).toBe(initialState);
  });

  test(<span class="hljs-string">"testAddReducer"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> testData = {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getSeconds()}</span>`</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"This is for the test section"</span>,
      <span class="hljs-attr">significance</span>: <span class="hljs-number">5</span>,
    };

    <span class="hljs-keyword">const</span> afterReducerOperation = ListSlice(
      initialState,
      testAddReducer(testData)
    );

    expect(afterReducerOperation).toStrictEqual({
      <span class="hljs-attr">value</span>: [initialState.value.at(<span class="hljs-number">0</span>), testData],
    });
  });
});
</code></pre>
<p>I added the test for <code>testAddReducer</code>. You can see that I imported the reducer as well.</p>
<p>Firstly, I'm initializing a new variable, <code>testData</code>, which contains the data I would like to push to the current state.</p>
<p>After that, we follow the same structure as before with <code>afterReducerOperation</code>. But instead of this <code>type: "unknown"</code> stuff, we add the reducer as the second argument. This receives the <code>testData</code> as a parameter – basically like you would see it in a dispatch.</p>
<p>Then, we expect this <code>afterReducerOperation</code> variable to be strictly equal to the value of an array, which has two entries: <code>initialState.value.at(0)</code> (the first entry of our <code>initialState</code>) and <code>testData</code>. And this test will pass like we actually expected it.</p>
<p>If we are trying to enter some other entries or change the current ones, you would be able to see this test failing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>forced error: I added a third entry to the array</em></p>
<h3 id="heading-how-to-make-the-button-click-function-work-again">How to make the button click function work again</h3>
<p>Remember the button click within the <code>List.js</code> component (for adding something to the <code>listData</code> state) that wasn't working anymore after we changed to the Redux setup? Let's quickly update that to make that logic work within a Redux environment for the sake of completeness. Since we have the required reducer now, this will be an easy step.</p>
<p>To make the test work again, which added a new element to the state, we have to adjust it a little on the frontend to implement the Redux logic. (Previously we used the useState hook for a local state.)</p>
<p>For this step, we are making use of the <code>dispatch()</code> function in order to reach out to the <code>testAddReducer</code>:</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-keyword">import</span> { testAddReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"../features/ListSlice"</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> listState = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.listReducers.value);
  <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">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> "<span class="hljs-attr">auto</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">500px</span>" }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a list<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">listStyleType:</span> "<span class="hljs-attr">none</span>" }}&gt;</span>
        {listState.map((listItem) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{listItem.id}</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"list-item"</span>&gt;</span>
              {listItem.description}
            <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">button</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span>
          dispatch(
            testAddReducer({
              id: `${new Date().getSeconds()}1`,
              description: "This is added",
              significance: 5,
            })
          )
        }
      &gt;
        This button can add a new entry to the list
      <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> List;
</code></pre>
<p>Besides the button logic, nothing else has changed in this file.</p>
<p>In the corresponding test (within <code>myFirstTesting.test.js</code> nothing has changed), if we now test everything – including this updated test – we will see that everything works fine:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>final test run</em></p>
<p>And that's pretty much it for fundamental slice and general Redux unit testing!</p>
<h2 id="heading-outlook-for-advanced-testing">🔭 Outlook for Advanced Testing</h2>
<p>There are different topics like <a target="_blank" href="https://redux-toolkit.js.org/api/createAsyncThunk">thunks</a> (or <a target="_blank" href="https://redux-toolkit.js.org/rtk-query/overview">RTK Query</a> as an alternative) which could also be tested. But I'm considering this as an advanced topic, and it would take some more time to explain these processes.</p>
<p>If you are not aiming to be an expert in testing at this point, the topics we discussed for unit tests in Redux in this tutorial should be sufficient for you.</p>
<p>Generally speaking, I would recommend diving deeper into so-called mocks, spies, and also snapshots. These will be helpful if you are working on some other more advanced tests. </p>
<p>The stuff with <code>renderWithProvider()</code> is basically based on such a mock – there, we artificially created a store with reducers and a provider to create this new <code>render()</code> function. So mocks are especially helpful for any third-party libraries, for example. </p>
<p>As I said, though, mocks, spies, and snapshots are more of an advanced topic to wrap your head around.</p>
<h2 id="heading-further-learning-opportunities">📣 Further Learning Opportunities</h2>
<p>I recently started to work on my first <a target="_blank" href="https://www.udemy.com/user/matthes-bar/">free Udemy course</a>. While this first free course covers the basics of the React Redux Toolkit with German audio and manually added English subtitles, I'm also planning to publish other Udemy courses completely in English in the future. </p>
<p>I would really appreciate it if you would check out this cost-free course in order to provide me with some feedback.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Redux-Powered React App ]]>
                </title>
                <description>
                    <![CDATA[ The Problem We're Solving In many cases when we want to create a small application, we might have some components that declare and use their own state. And in a few cases, a component might want to share the state with its immediate children.  We can... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-redux-powered-react-app/</link>
                <guid isPermaLink="false">66ba5d40968a8cd3b478a8ea</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham De Roy ]]>
                </dc:creator>
                <pubDate>Wed, 03 Aug 2022 21:51:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/Group-58.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-the-problem-were-solving">The Problem We're Solving</h2>
<p>In many cases when we want to create a small application, we might have some components that declare and use their own state. And in a few cases, a component might want to share the state with its immediate children. </p>
<p>We can handle these situations just by declaring states locally within a component – and maybe pass the state to its children in the form of props if needed (which is also known as prop drilling). </p>
<p>But if your application grows in size, you might need to pass state to a child which might be several steps down the hierarchy. You might also need to use a common state between sibling components. </p>
<p>Sure, in the case of state sharing between sibling components we can declare the state in their parents and then pass the state down to their children by prop drilling. But that may not always be feasible and has its own disadvantages that we will see in a bit. </p>
<p>Just consider the following diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Group-49.png" alt="Group-49" width="600" height="400" loading="lazy"></p>
<p>This is a schematic representation of a component file structure in a typical React application. </p>
<p>Let's say we need to share a common state between Child 5 and Child 6. In that case we can very well declare a state in their parent (that is, Child 2) and pass the state down to the two children (5 and 6). </p>
<p>All good as of now. But what if we need to have the same piece of state in Child 3? In that case we would need to declare the state in the common parent/grandparent of Children 5, 6, and 3 – that is, the App component. </p>
<p>Similarly what if we want to share a state between Children 4, 11, and 10 which are far away from each other in the tree? We would again need to create the state in the App component and then do multiple levels of prop drilling to pass the state from App to these components. </p>
<p>And as time passes and our app grows in size, it will start making our App component or any other such common parent component cluttered with unnecessary state declarations. These declarations aren't used directly by these components but are used by some of their far-down children.</p>
<h2 id="heading-disadvantages-of-multi-step-prop-drilling">Disadvantages of Multi-Step Prop Drilling</h2>
<p>There are primarily two disadvantages with multi level prop drilling. They are:</p>
<ul>
<li><strong>Unnecessary bloating of components:</strong> As discussed above, as our app grows in size, some common parent components might get bloated with unnecessary state declarations. And these components might not directly use those declarations, but they might be used by some of their distant children. Some other components might also get bloated which are just acting as prop passers to a child component. This will also negatively affect code readability.</li>
<li><strong>Unnecessary re-rendering:</strong> Unnecessary re-rendering is a big no no for a client-side application. Unnecessary re-renders can make an app slow, laggy, unresponsive and give a bad user experience. In React, re-renderings are caused by state or prop changes, among other reasons. So if a component is not actually using a state and is only acting as a passage from parent to child for the props, then it might also get re-rendered unnecessarily when the state/ props changes. See the below picture to understand it better</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Group-52-1.png" alt="Group-52-1" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-solution-to-this-problem">The Solution to this Problem</h2>
<p>This is why we use a state management app like Redux or MobX to handle the above scenarios of state management in a more uniform and efficient way. </p>
<p>In these kind of state management solutions like Redux, we can create a global state and put it in a store. Whichever component requires any state from that store can easily get it by subscribing to the store. This way we can get rid of both the above disadvantages.</p>
<ul>
<li><strong>Decluttering of components:</strong> Getting state on demand from the component which is "actually" using it can declutter many of our components to a large extent by removing all unnecessary prop drilling.</li>
<li><strong>No more unnecessary re-renders:</strong> As we do not have components that just act as a prop passer, we also avoid unnecessary re-rendering of those components. Only the components that uses a piece of the global state re-render when the state changes which is a desired behavior.</li>
</ul>
<h2 id="heading-what-youll-learn-here">What You'll Learn Here</h2>
<p>In this tutorial, you will learn how to set up your own Redux-powered React application. We will create a react application and setup up redux to be able to manage state globally so that any component can access any part of the state (hence the name redux powered react app). Some of the other alternative of redux that one can try are MobX, Zustand etc, but for this article we will be using redux.</p>
<p>We will go through how to create the store and connect it to the application. We'll also see how to write actions and dispatch them on user interactions. Then we'll see how to make reducers and update the store, read the store from other components which are children of App, and much more. </p>
<p>I'll also provide all the important code snippets along the way so that you can quickly spin up the application as you read and code along.</p>
<p>To give you a glimpse in the beginning, this is what we will build by the end:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/finalAppDemo.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will be creating a basic application where we can add and remove items in a cart. We will manage the state changes in the Redux store and display the information in the UI.</p>
<h2 id="heading-before-we-start">Before We Start</h2>
<p>Before proceeding with this tutorial, you should be familiar with the Redux store, actions, and reducers.</p>
<p>If you're not, you can go through my last article that I wrote on Redux (if you haven't yet): <strong><a target="_blank" href="https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/">What is Redux? Store, Actions, and Reducers Explained for Beginners</a>.</strong> </p>
<p>This will help you understand the current article. In this previous tutorial, I tried to explain the fundamental principles/ concepts of Redux. I covered what the store is, what actions are, and how reducers work. I also discuss what makes Redux predictable along with an example.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/despicable-me-minions.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-initial-code-setup">Initial Code Setup</h2>
<p>Let's get everything we need setup for our project. Just follow these steps and you'll be up and running in no time.</p>
<h3 id="heading-1-create-a-react-app-with-the-create-react-app-command">1. Create a React app with the create-react-app command</h3>
<pre><code class="lang-node">npx create-react-app react-app-with-redux
</code></pre>
<h3 id="heading-2-go-to-the-newly-created-folder">2. Go to the newly created folder</h3>
<p>Just type this command to navigate to the new folder:</p>
<pre><code class="lang-shell">cd react-app-with-redux
</code></pre>
<h3 id="heading-3-install-redux-and-the-react-redux-libraries">3. Install Redux and the react-redux libraries</h3>
<p>You can install Redux and react-redux like this:</p>
<pre><code class="lang-node">npm install redux react-redux
</code></pre>
<h3 id="heading-4-run-the-application">4. Run the application</h3>
<p>You can run your new app with the following command:</p>
<pre><code class="lang-node">npm start
</code></pre>
<h2 id="heading-how-to-build-the-main-app">How to Build the Main App</h2>
<h3 id="heading-5-how-to-create-the-reducer">5. How to create the Reducer</h3>
<p>To create a reducer, first create a folder inside <code>src</code> named <code>actionTypes</code>. Then create a file inside it named <code>actionTypes.js</code>. This file will contain all the <strong>actions</strong> the application will be dealing with.</p>
<p>Add the following lines in <code>actionTypes.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD_ITEM = <span class="hljs-string">"ADD_ITEM"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DELETE_ITEM = <span class="hljs-string">"DELETE_ITEM"</span>;
</code></pre>
<p>Since our app will have the functionality of adding and deleting items, we need the above two action types.</p>
<p>Next create a folder inside the <code>src</code> called <code>reducers</code> and create a new file in it named <code>cartReducer.js</code>. This file will contain all the reducer logic related to the <strong>cart</strong> component. </p>
<p><strong>Note</strong>: We will create the view/ UI in step 8, so hold on for that.</p>
<p>Add the following lines in <code>cartReducer.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { ADD_ITEM, DELETE_ITEM } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actionTypes/actionTypes"</span>;

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">const</span> cartReducer = <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_ITEM:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">numOfItems</span>: state.numOfItems + <span class="hljs-number">1</span>,
      };

    <span class="hljs-keyword">case</span> DELETE_ITEM:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">numOfItems</span>: state.numOfItems - <span class="hljs-number">1</span>,
      };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>As we discussed it <a target="_blank" href="https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/">in my previous tutorial</a>, we created an <strong>initial state</strong> for the app and assigned it to the default parameter of <code>state</code> in the <code>cartReducer</code> function. </p>
<p>This function switches on the <strong>type of action</strong> dispatched. Then depending on whichever case matches with the action type, it makes necessary changes in the state and returns a fresh new instance of the updated state. </p>
<p>If none of the action types matche, then the state is returned as it is. </p>
<p>Finally we make a <strong>default export</strong> of the <code>cakeReducer</code> function to use it in the store creation process.</p>
<h3 id="heading-6-how-to-create-the-store-and-provide-it-to-the-app">6. How to create the store and provide it to the app</h3>
<p>Create a file inside <code>src</code> with the name <code>store.js</code> and create the store using this command:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> store = createStore()
</code></pre>
<p>Add the following lines in <code>store.js</code>:</p>
<pre><code class="lang-js"><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> { cartReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"./reducers/cartReducer"</span>;

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>Now it's time to provide this <code>store</code> to the <code>App</code> component. For this we'll use the <code>&lt;Provider&gt;</code> tag that we get from the <code>react-redux</code> library. </p>
<p>We wrap the whole <code>App</code> component inside the <code>&lt;Provider&gt;</code> tag using the following syntax:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// rest of the code ...</span>

&lt;Provider store={store}&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>App Component<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        <span class="hljs-comment">// child components of App/ other logic</span>
&lt;/Provider&gt;

<span class="hljs-comment">// rest of the code ...</span>
</code></pre>
<p>By wrapping the <code>App</code> component inside the <code>&lt;Provider&gt;</code> tag, all the children component of <code>App</code> will get access of the <code>store</code>. You can read my previous article on <a target="_blank" href="https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/">What is Redux? Store, Actions, and Reducers Explained for Beginners</a> to know more.</p>
<p>Continuing with <code>App.js</code>, add the following lines to the file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.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>;

<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">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>&gt;</span>App Component<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>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-7-create-the-actions">7. Create the Actions</h3>
<p>Now create a folder inside <code>src</code> called <code>actions</code> and create a file inside it called <code>cartAction.js</code>. Here we will add all the actions to be <strong>dispatched</strong> on some user interactions. </p>
<p>Add the following lines in the <code>cartAction.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { ADD_ITEM, DELETE_ITEM } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actionTypes/actionTypes"</span>;

<span class="hljs-keyword">const</span> addItem = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: ADD_ITEM,
  };
};

<span class="hljs-keyword">const</span> deleteItem = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: DELETE_ITEM,
  };
};

<span class="hljs-keyword">export</span> { addItem, deleteItem };
</code></pre>
<p>In the above code we created two action creators (pure JS functions that returns <code>action</code> object) called <code>addItem()</code> and <code>deleteItem()</code>. Both the action creators return <code>action</code> objects with a specific <code>type</code>. </p>
<p><strong>Note</strong>: Each <code>action</code> object must have a unique <code>type</code> value. Along with it, any additional data passed with the action object is optional and will depend on the logic used for updating the <code>state</code></p>
<h3 id="heading-8-how-to-create-the-viewui">8. How to create the view/UI</h3>
<p>Now that we have created all the required entities such as the store, actions, and Reducers, it's time to create the UI elements. </p>
<p>Create a <code>component</code> folder inside <code>src</code> and a <code>Cart.js</code> file inside it. Add the following lines inside <code>Cart.js</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">const</span> Cart = <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> <span class="hljs-attr">className</span>=<span class="hljs-string">"cart"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Number of items in Cart:<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">className</span>=<span class="hljs-string">"green"</span>&gt;</span>Add Item to Cart<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">className</span>=<span class="hljs-string">"red"</span>&gt;</span>Remove Item from 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-keyword">export</span> <span class="hljs-keyword">default</span> Cart;
</code></pre>
<p>Add this <code>Cart</code> component in the <code>App.js</code> file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.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>;
<span class="hljs-keyword">import</span> Cart <span class="hljs-keyword">from</span> <span class="hljs-string">"./component/Cart"</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">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">Cart</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Just to make it a bit presentable, I have added a bit of basic styling in <code>App.css</code> as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">letter-spacing</span>: <span class="hljs-number">2px</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">400</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">23px</span> <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">display</span>: inline-block;
  <span class="hljs-attribute">text-decoration</span>: none;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}
<span class="hljs-selector-class">.green</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">6</span>, <span class="hljs-number">172</span>, <span class="hljs-number">0</span>);
}
<span class="hljs-selector-class">.red</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">221</span>, <span class="hljs-number">52</span>, <span class="hljs-number">66</span>);
}
<span class="hljs-selector-class">.red</span><span class="hljs-selector-pseudo">:disabled</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">193</span>, <span class="hljs-number">191</span>, <span class="hljs-number">191</span>);
  <span class="hljs-attribute">cursor</span>: not-allowed;
}
<span class="hljs-selector-class">.cart</span> {
  <span class="hljs-attribute">text-align</span>: center;
}
</code></pre>
<p>This is how the UI looks as of now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/Screenshot-2022-05-20-at-20.01.01.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-9-how-to-read-and-access-the-store-using-the-useselector-hook">9. How to read and access the store using the <code>useSelector</code> hook</h3>
<p><code>useSelector</code> is a hook provided by the <strong>react-redux</strong> library that helps us read the <code>store</code> and its content(s). </p>
<p>Import the hook from <code>react-redux</code> and use the following syntax to read the store with <code>useSelector</code> hook:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-comment">// rest of the code</span>
<span class="hljs-keyword">const</span> state = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state);

<span class="hljs-comment">// rest of the code</span>
</code></pre>
<p>After adding the <code>useSelector</code> hook, your <code>Cart.js</code> file will look something like this:</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> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;

<span class="hljs-keyword">const</span> Cart = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> state = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"store"</span>, state);
  <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"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Number of items in Cart:<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">className</span>=<span class="hljs-string">"green"</span>&gt;</span>Add Item to Cart<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">className</span>=<span class="hljs-string">"red"</span>&gt;</span>Remove Item from 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-keyword">export</span> <span class="hljs-keyword">default</span> Cart;
</code></pre>
<p>Console logging the state will give us the initial state that we set in the reducer file in step 5.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/Screenshot-2022-05-21-at-01.10.28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-10-how-to-dispatch-an-action-on-button-click-with-the-usedispatch-hook">10. How to dispatch an action on button click with the <code>useDispatch</code> hook</h3>
<p>The react-redux library gives us another hook called the <code>useDispatch</code> hook. It helps us dispatch the actions or action creators which in turn return actions. The syntax is as follows:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> dispatch = useDispatch();

dispatch(actionObject or calling the action creator);
</code></pre>
<p>Thus adding a dispatcher into our <code>Cart.js</code> will finally make the file look something like this:</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> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { addItem, deleteItem } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions/cartAction"</span>;

<span class="hljs-keyword">const</span> Cart = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> state = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state);
  <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">"cart"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Number of items in Cart: {state.numOfItems}<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">{()</span> =&gt;</span> {
          dispatch(addItem());
        }}
      &gt;
        Add Item to Cart
      <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">disabled</span>=<span class="hljs-string">{state.numOfItems</span> &gt;</span> 0 ? false : true}
        onClick={() =&gt; {
          dispatch(deleteItem());
        }}
      &gt;
        Remove Item 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-keyword">export</span> <span class="hljs-keyword">default</span> Cart;
</code></pre>
<p>Note how on click of the <strong>Add Item to Cart</strong> button, we <code>dispatch</code> the action creator <code>addItem()</code> that we created in step no. 7. </p>
<p>Similarly on click on the <strong>Remove Item from Cart</strong> button, we dispatch the action creator with <code>deleteItem()</code>. </p>
<p>The <code>state</code> variable stores the state of the app, which is basically an object with a key <code>numOfItems</code>. So <code>state.numOfItems</code> gives us the current number of items value in the store. </p>
<p>We display this information in the view in the line <code>&lt;h2&gt;Number of items in Cart: {state.numOfItems}&lt;/h2&gt;</code>. </p>
<p>To dig a bit deeper, when a user clicks the Add Item to Cart button, it dispatches the <code>addItem()</code> action creator. This, in turn, returns an <code>action</code> object with type <code>type: ADD_ITEM</code>. </p>
<p>As mentioned in <a target="_blank" href="https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/">my previous tutorial</a>, when an action is dispatched, all the reducers become active. </p>
<p>Currently in this example we have only one reducer – <code>cartReducer</code>. So it becomes active and listens to the <code>action</code> dispatched. </p>
<p>As shown in step 5, the reducer takes the state and the action as input, switches on the <code>action type</code> and <strong>returns the fresh new instance of the updated state</strong>. </p>
<p>In this example, when the action with <code>type: ADD_ITEM</code> matches the first switch case, it first makes a copy of the entire state using the spread operator <code>...state</code>. Then it makes the necessary update – which in the case of adding items is <code>numOfItems: state.numOfItems + 1</code> (that is increasing the <code>numOfItems</code> by 1). </p>
<p>Similarly, using the same logic, on clicking on the Remove Item from Cart button, an action with type <code>type: DELETE_ITEM</code> is dispatched which goes and decreases the <code>numOfItems</code> by 1. </p>
<p>Here is the demo of the working app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/finalAppDemo-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Notice how we were able to control the behavior of the Remove Item from Cart button based on the value of <code>numOfItems</code> in the Redux store. As a negative number of items does not makes sense, we disabled the Remove Item from Cart button if <code>state.numOfItems &lt;= 0</code>. </p>
<p>This way we are able to prevent the user from decreasing the number of items in the cart if its already 0. </p>
<p>This was a basic example to show you how we can <strong>control the behavior of various DOM elements</strong> based on the internal state of the app. </p>
<p>And there you go! We just finished setting up our first Redux-powered React application. Now you can go ahead and create various other components based on your requirements and share a common global state among them.</p>
<h2 id="heading-github-repo">GitHub Repo</h2>
<p>Here's the GitHub repo of the project so you can examine the full source code if you like: <a target="_blank" href="https://github.com/sohamderoy/blog-setup-react-app-with-redux/tree/master">GitHub repo</a></p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we learned how to quickly spin up a Redux-powered React application. </p>
<p>Along the way, we learned how to:</p>
<ul>
<li>Create actions, action creators, reducers, and the store</li>
<li>Provide the store to the app using <code>&lt;Provider&gt;</code></li>
<li>Read/ access the store from components using the <code>useSelector</code> hook and display the state information in the UI</li>
<li>Dispatch the actions on user events such as button clicks, using the <code>useDispatch</code> hook</li>
<li>Control the DOM elements' behavior with logic based on the state of the application</li>
<li>We learnt what are the disadvantages of in-efficient state management and multiple level of prop drilling </li>
</ul>
<h2 id="heading-additional-resources">Additional Resources</h2>
<p>Here are some additional resources that you can look into to learn more about Redux</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/">What is Redux? Store, Actions, and Reducers Explained for Beginners</a></li>
<li><a target="_blank" href="https://redux.js.org/introduction/getting-started">Official Redux Docs</a></li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Thanks for reading! I really hope you enjoyed reading about how to spin up a Redux-powered React application and found this tutorial useful.</p>
<p>Do consider sharing it with your friends, as I'd really appreciate that. Follow me on LinkedIn and Twitter and stay tuned for more amazing content! Peace out! 🖖</p>
<h3 id="heading-social-links">Social Links</h3>
<ul>
<li><a target="_blank" href="https://www.linkedin.com/feed/">LinkedIn</a></li>
<li><a target="_blank" href="https://www.sohamderoy.dev/">Website</a></li>
<li><a target="_blank" href="https://blogs.sohamderoy.dev">Other Blogs by me</a></li>
<li><a target="_blank" href="https://twitter.com/_sohamderoy">Twitter</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Redux? Store, Actions, and Reducers Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Redux is a predictable state container for JavaScript apps. So what does that really mean? If we dig deeper into this statement, we see that Redux is a state management library that you can use with any JS library or framework like React, Angular, or... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-redux-store-actions-reducers-explained/</link>
                <guid isPermaLink="false">66ba5d480013ba5d5012bcb5</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham De Roy ]]>
                </dc:creator>
                <pubDate>Wed, 27 Jul 2022 15:48:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/Group-60.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Redux is a predictable state container for JavaScript apps. So what does that really mean?</p>
<p>If we dig deeper into this statement, we see that Redux is a state management library that you can use with any JS library or framework like React, Angular, or Vue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/1-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this article, we'll be covering the fundamentals of Redux. We will learn what Redux is at its core along with its three key principles. </p>
<p>We will also see how some of its core building blocks work, such as store, actions, and reducers and how they all come together and make Redux the global state management library that it is.</p>
<p>As a prerequisite, I will be assuming that you're familiar with React.</p>
<h2 id="heading-why-use-redux">Why Use Redux?</h2>
<p>Well, an application has its state, which can be a combination of the states of its internal components. </p>
<p>Let's take an e-commerce website for example. An e-commerce website will have several components like the cart component, user profile component, previously viewed section component, and so on. </p>
<p>We'll take the cart component which displays the number of items in a user's cart. The state of the cart component will consist of all the items the user has added to the cart and the total number of those items. At all times the application is up and running, this component has to show the updated number of items in the user's cart. </p>
<p>Whenever a user adds an item to the cart, the application has to internally handle that action by adding that item to the cart object. It has to maintain its state internally and also show the user the total number of items in the cart in the UI. </p>
<p>Similarly, removing an item from the cart should decrease the number of items in the cart internally. It should remove the item from the cart object and also display the updated total number of items in the cart in the UI. </p>
<p>We may very well maintain the internal state of the components inside them, but as and when an application grows bigger, it may have to share some state between components. This is not just only to show them in the view, but also to manage or update them or perform some logic based on their value. </p>
<p>This task of handling multiple states from multiple components efficiently can become challenging when the application grows in size.</p>
<p>This is where Redux comes into the picture. Being a state management library, Redux will basically store and manage all the application's states. </p>
<p>It also provides us with some important APIs using which we can make changes to the existing state as well as fetch the current state of the application. </p>
<h2 id="heading-what-makes-redux-predictable">What Makes Redux Predictable?</h2>
<p>State is <strong>Read-only</strong> in Redux. What makes Redux predictable is that to make a change in the state of the application, we need to dispatch an action which describes what changes we want to make in the state. </p>
<p>These actions are then consumed by something known as reducers, whose sole job is to accept two things (the action and the current state of the application) and return a new updated instance of the state. </p>
<p>We'll talk more about actions and reducers in the following sections. </p>
<p>Note that reducers do not change any part of the state. Rather a reducer produces a new instance of the state with all the necessary updates. </p>
<p>According to <a class="user-mention" href="https://hashnode.com/@gaearon">Dan Abramov</a> (the creator of Redux) himself,  </p>
<blockquote>
<p>"Actions can be recorded and replayed later, so this makes state management predictable. With the same actions in the same order, you're going to end up in the same state." </p>
</blockquote>
<p>So continuing with our above example of an e-commerce website, if the initial state of the cart is that it has 0 items, then an action of <strong>adding one item</strong> to the cart will increase the number of items in the cart by 1. And firing the action of <strong>adding one item</strong> to the cart again will increase the number of items in the cart to 2. </p>
<p>Given an initial state, with a specific list of <strong>actions</strong> in a specific order, it'll always provide us with the exact same final state of the entity. This is how Redux makes state management predictable.</p>
<p>In the following section, we will dive deep into the core concepts of Redux – the store, actions and reducers.</p>
<h2 id="heading-core-principles-of-redux">Core Principles of Redux</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-1-what-is-the-redux-store">1. What is the Redux Store?</h3>
<blockquote>
<p>The global state of an application is stored in an object tree within a single store – <a target="_blank" href="https://redux.js.org/understanding/thinking-in-redux/three-principles">Redux docs</a></p>
</blockquote>
<p>The Redux store is the main, central bucket which stores all the states of an application. It should be considered and maintained as a <strong>single source of truth</strong> for the state of the application. </p>
<p>If the <code>store</code> is provided to the <strong>App.js</strong> (by wrapping the <code>App</code> component within the <code>&lt;Provider&gt;</code> <code>&lt;/Provider&gt;</code> tag) as shown in the code snippet below, then all its children (children components of <code>App.js</code>) can also access the state of the application from the store. This makes it act as a global state. </p>
<pre><code class="lang-js"><span class="hljs-comment">// src/index.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> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</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> createStore <span class="hljs-keyword">from</span> <span class="hljs-string">'./createReduxStore'</span>

<span class="hljs-keyword">const</span> store = createStore()

<span class="hljs-comment">// As of React 18</span>
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>))
root.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>
)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The state of the whole application is stored in the form of a <strong>JS object tree</strong> in a <strong>single store</strong> as shown below. </p>
<pre><code class="lang-js"><span class="hljs-comment">// this is how the store object structure looks like</span>
{
    <span class="hljs-attr">noOfItemInCart</span>: <span class="hljs-number">2</span>,
    <span class="hljs-attr">cart</span>: [
        {
            <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Chamber of Secrets"</span>,
            <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
        },
        {
            <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Prisoner of Azkaban"</span>,
            <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>
        }
    ]
}
</code></pre>
<h3 id="heading-2-what-are-actions-in-redux">2. What Are Actions in Redux?</h3>
<blockquote>
<p>The only way to change the state is to emit an action, which is an object describing what happened – <a target="_blank" href="https://redux.js.org/understanding/thinking-in-redux/three-principles">Redux Docs</a></p>
</blockquote>
<p>As mentioned above, state in Redux is read-only. This helps you restrict any part of the view or any network calls to write/update the state directly. </p>
<p>Instead, if anyone wants to change the state of the application, then they'll need to express their intention of doing so by <strong>emitting or dispatching an action</strong>. </p>
<p>Let's take the example of the above store example where we have 2 books in the store: <em>"Harry Potter and the Chamber of Secrets"</em> and <em>"Harry Potter and the Prisoner of Azkaban"</em>. There's just one copy of each. </p>
<p>Now if the user wants to add another item to the cart, then they will have to click on the <strong>"Add to Cart"</strong> button next to the item. </p>
<p>On the click of the <strong>"Add to Cart"</strong> button, an action will be dispatched. This action is nothing but a JS object describing what changes need to be done in the store. Something like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Rest of the code</span>

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

<span class="hljs-keyword">const</span> addItemToCart = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> {
    <span class="hljs-attr">type</span>: <span class="hljs-string">"ADD_ITEM_TO_CART"</span>
    <span class="hljs-attr">payload</span>: {
        <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Goblet of Fire"</span>,
        <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
        }
    }
}

&lt;button onClick = {<span class="hljs-function">() =&gt;</span> dispatch(addItemToCart())}&gt;Add to cart&lt;/button&gt;

<span class="hljs-comment">// Rest of the code</span>
</code></pre>
<p>Note how in the above example, we dispatch an action on click of the button. Or rather, to be more specific, we dispatch something known as an <strong>action creator</strong> – that is, the function <code>addItemToCart()</code>. This in turn returns an <code>action</code> which is a plain JS object describing the purpose of the action denoted by the <code>type</code> key along with any other data required for the state change. In this case, it's the name of the book to be added to the cart denoted by the <code>payload</code> key. </p>
<p><strong>Every action must have at least</strong> a <code>type</code> associated with it. Any other detail that needs to be passed is optional and will depend on the type of action we dispatch. </p>
<p>For example, the above code snippet dispatches the following action:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Action that got created by the action creator addItemToCart()</span>

{
    <span class="hljs-attr">type</span>: <span class="hljs-string">"ADD_ITEM_TO_CART"</span> <span class="hljs-comment">// Note: Every action must have a type key</span>
    <span class="hljs-attr">payload</span>: {
        <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Goblet of Fire"</span>,
        <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
    }
}
</code></pre>
<h3 id="heading-3-what-are-reducers-in-redux">3. What Are Reducers in Redux?</h3>
<blockquote>
<p>To specify how the state tree is transformed by actions, we write pure reducers – <a target="_blank" href="https://redux.js.org/understanding/thinking-in-redux/three-principles">Redux docs</a></p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Reducers, as the name suggests, take in two things: <strong>previous state</strong> and <strong>an action</strong>. Then they reduce it (read it return) to one entity: the <strong>new updated instance of state</strong>. </p>
<p>So reducers are basically pure JS functions which take in the previous state and an action and return the newly updated state. </p>
<p>There can either be one reducer if it is a simple app or multiple reducers taking care of different parts or slices of the global state in a bigger application. </p>
<p>For example, there can be a reducer handling the state of the cart in a shopping application, then there can be a reducer handling the user details part of the application, and so on. </p>
<p>Whenever an action is dispatched, <strong>all the reducers are activated</strong>. Each reducer filters out the action using a switch statement switching on the <strong>action type</strong>. Whenever the switch statement matches with the action passed, the corresponding reducers take the necessary action to make the update and return a fresh new instance of the global state. </p>
<p>Continuing with our above example, we can have a reducer as follows:</p>
<pre><code class="lang-js">
<span class="hljs-keyword">const</span> initialCartState = {    
    <span class="hljs-attr">noOfItemInCart</span>: <span class="hljs-number">0</span>,          
    <span class="hljs-attr">cart</span>: []                              
}

<span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> </span>
<span class="hljs-comment">// It is important to pass an initial state as default to </span>
<span class="hljs-comment">// the state parameter to handle the case of calling </span>
<span class="hljs-comment">// the reducers for the first time when the </span>
<span class="hljs-comment">// state might be undefined</span>

<span class="hljs-keyword">const</span> cartReducer = <span class="hljs-function">(<span class="hljs-params">state = initialCartState, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"ADD_ITEM_TO_CART"</span>: 
            <span class="hljs-keyword">return</span> {
                ...state,
                <span class="hljs-attr">noOfItemInCart</span>: state.noOfItemInCart + <span class="hljs-number">1</span>,
                <span class="hljs-attr">cart</span> : [
                    ...state.cart,
                    action.payload
                ]
            }
        <span class="hljs-keyword">case</span> <span class="hljs-string">"DELETE_ITEM_FROM_CART"</span>:
            <span class="hljs-keyword">return</span> {
                <span class="hljs-comment">// Remaining logic</span>
            }
        <span class="hljs-attr">default</span>: 
            <span class="hljs-keyword">return</span> state  
    }       <span class="hljs-comment">// Important to handle the default behaviour</span>
}           <span class="hljs-comment">// either by returning the whole state as it is </span>
            <span class="hljs-comment">// or by performing any required logic</span>
</code></pre>
<p>In the above code snippet, we created a reducer called <code>cartReducer</code> which is a pure JS function. This function accepts two parameters: <code>state</code> and <code>action</code>. </p>
<p>Note that the <code>state</code> parameter is a default parameter which accepts an initial state. This is to handle the scenario when <strong>the reducer is called for the first time</strong> when the <code>state</code> value is <code>undefined</code>.  </p>
<p>Also note that every reducer should handle the <code>default</code> case where, if none of the switch cases match with the passed action, then the reducer should return <code>state</code> as it is or perform any required logic on it before passing the state.</p>
<p>Whenever we dispatch an action with a certain type, we need to make sure to have appropriate reducers to handle that action. </p>
<p>In the above example, on clicking the button, we had dispatched an <strong>action</strong> with an <strong>action creator</strong> called <code>addItemToCart()</code>. This action creator has dispatched an action with the <code>type</code> <code>ADD_ITEM_TO_CART</code>. </p>
<p>Next, we have created a <strong>reducer</strong> called <code>cartReducer</code> which takes the state (with the default initial state) and the action as parameters. It switches on the <strong>action type</strong>, and then whichever case matches with the dispatched action type, it makes the necessary update and returns the fresh new version of the updated state. </p>
<p>Note here that <strong>state in redux is immutable</strong>. So, the reducers make a copy of the entire current state first, make the necessary changes, and then return a fresh new instance of the state – with all the necessary changes/ updates. </p>
<p>So in the above example, we first make a copy of the entire state using the spread operator <code>...state</code>. Then we increment the <code>noOfItemInCart</code> by 1, update the cart array by adding the new object passed in the <code>action.payload</code> shown below, and then finally return the updated object.</p>
<pre><code class="lang-js">{
    <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Goblet of Fire"</span>,
    <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
}
</code></pre>
<p>After the reducers have updated the state, if we go and <code>console.log</code> the <code>state</code>, then we would see the following result:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Updated store</span>

{
    <span class="hljs-attr">noOfItemInCart</span>: <span class="hljs-number">3</span>, <span class="hljs-comment">// Incremented by 1</span>
    <span class="hljs-attr">cart</span>: [
        {
            <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Chamber of Secrets"</span>,
            <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
        },
        {
            <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Prisoner of Azkaban"</span>,
            <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>
        },
        { <span class="hljs-comment">// Newly added object</span>
            <span class="hljs-attr">bookName</span>: <span class="hljs-string">"Harry Potter and the Goblet of Fire"</span>,
            <span class="hljs-attr">noOfItem</span>: <span class="hljs-number">1</span>,
        }
    ]
}
</code></pre>
<h2 id="heading-summary">Summary</h2>
<p>In short, the following three principles completely govern how Redux works:</p>
<ul>
<li>The global state of an application is stored in an object tree within a single <strong>store</strong></li>
<li>The only way to change the state is to emit an <strong>action</strong>, which is an object describing what happened</li>
<li>To specify how the state tree is transformed by actions, we write <strong>pure reducers</strong></li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Thanks for reading! I really hope you enjoyed learning about Redux and its core principles and found this tutorial useful. </p>
<p>Do consider sharing it with your friends, I'd really appreciate that.  Stay tuned for more amazing content. Peace out! 🖖</p>
<h3 id="heading-social-links">Social Links</h3>
<ul>
<li><a target="_blank" href="https://www.linkedin.com/feed/">LinkedIn</a></li>
<li><a target="_blank" href="https://www.sohamderoy.dev/">Website</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/sohamderoy">Other Blogs</a></li>
<li><a target="_blank" href="https://twitter.com/_sohamderoy">Twitter</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Redux Toolkit – The Recommended Way to Use Redux ]]>
                </title>
                <description>
                    <![CDATA[ Redux Toolkit is an opinionated toolset for efficient Redux development created by the Redux team. It is the the standard and recommended way to write Redux logic and manage state in your JavaScript applications. We just published a full course on th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-redux-toolkit-the-recommended-way-to-use-redux/</link>
                <guid isPermaLink="false">66b2050239b555ffda8bfea6</guid>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 20 Apr 2022 13:33:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/reduxtoolkit.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Redux Toolkit is an opinionated toolset for efficient Redux development created by the Redux team. It is the the standard and recommended way to write Redux logic and manage state in your JavaScript applications.</p>
<p>We just published a full course on the freeCodeCamp.org YouTube channel that will teach you how to use Redux Toolkit.</p>
<p>John Smilga published this course. He has created many very popular courses on the freeCodeCamp.org YouTube channel.</p>
<p>Redux is a JavaScript library for managing application state. It is most commonly used with React, but can be used with other JavaScript frameworks as well.</p>
<p>Redux Toolkit is a set of tools that helps simplify Redux development. It includes utilities for creating and managing Redux stores, as well as for writing Redux actions and reducers.</p>
<p>The Redux team recommends using Redux Toolkit anytime you need to use Redux. In this course you will learn how to use Redux Toolkit in your own applications.</p>
<p>Here are the sections covered in this course:</p>
<ul>
<li>Setup Store</li>
<li>Create Slice</li>
<li>Dev Tools</li>
<li>useSelector()</li>
<li>Hero Icons</li>
<li>Local Data</li>
<li>Render List</li>
<li>Cart Item</li>
<li>Clear Cart</li>
<li>Return State</li>
<li>Remove Item</li>
<li>Toggle Amount</li>
<li>Calculate Totals</li>
<li>Create Modal</li>
<li>Modal Complete</li>
<li>createAsyncThunk</li>
<li>createAsyncThunk Options</li>
</ul>
<p>Watch the full course below or on <a target="_blank" href="https://youtu.be/bbkBuqC1rU4">the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/bbkBuqC1rU4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React + WebSockets Project – Build a Real-Time Order Book Application ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, we will see how to build an Order Book web application, that we'll use to display real-time cryptocurrency info. We will use React with Typescript for creating the UI, Redux for managing the application state, and styled-components ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-websockets-project-build-real-time-order-book-app/</link>
                <guid isPermaLink="false">66d4605e230dff0166905835</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ styled-components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ websocket ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mihail Gaberov ]]>
                </dc:creator>
                <pubDate>Tue, 19 Apr 2022 17:15:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/react-and-websockets-articlde.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, we will see how to build an Order Book web application, that we'll use to display real-time cryptocurrency info.</p>
<p>We will use <a target="_blank" href="https://create-react-app.dev/docs/adding-typescript/">React with Typescript</a> for creating the UI, <a target="_blank" href="https://redux.js.org/">Redux</a> for managing the application state, and <a target="_blank" href="https://styled-components.com/">styled-components</a> for applying the styling. And last, but not least, we'll use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket">WebSockets</a> for fetching the data feeds.</p>
<h3 id="heading-github-repo">GitHub Repo</h3>
<p>💡 If you want to skip the reading, <a target="_blank" href="https://github.com/mihailgaberov/orderbook">here</a> 💁 is the GitHub repository with a detailed <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/README.md">README</a> 🙌, and <a target="_blank" href="https://orderbook-mihailgaberov.vercel.app/">here</a> you can see the live demo.</p>
<h2 id="heading-what-is-an-order-book">What is an Order Book?</h2>
<p>An <a target="_blank" href="https://www.coindesk.com/crypto-trading-101-how-to-read-an-exchange-order-book">Order Book</a> is an application that usually displays some kind of information related to buying and selling stuff.</p>
<p>💡 The most common use case is showing data for various assets, such as stocks, bonds, currencies, and even cryptocurrencies.</p>
<h2 id="heading-why-would-i-need-an-order-book">Why Would I Need an Order Book?</h2>
<p>In practice, Order Books are used by traders to watch the fluctuations of the bidding price and the asking price of certain products – currencies, stocks, and so on.</p>
<p>This is happening real time, so the changes can be very rapid. Here is where WebSockets will come in handy, as you will see later.</p>
<p>In the past, people did something similar on paper, but the ‘real-time' part was impossible, of course.</p>
<p>A regular Order Book usually has two sides: buying (or bidding), shown in green on the left side and selling (or asking), red, on the right.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-43.png" alt="Classic Orderbook" width="600" height="400" loading="lazy"></p>
<p><em>Classic Order book</em></p>
<h2 id="heading-the-plan-for-our-order-book-app">The Plan for our Order Book App</h2>
<p>Our Order Book app will consist of five parts:</p>
<ul>
<li><p>order book main view</p>
</li>
<li><p>grouping select box</p>
</li>
<li><p>Toggle Feed button</p>
</li>
<li><p>Kill Feed button</p>
</li>
<li><p>Status Message.</p>
</li>
</ul>
<p>The app design will look as shown below. Note that the Status Message component, that you will see in the my implementation, is missing on these screenshots:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-60.png" alt="Desktop layout" width="600" height="400" loading="lazy"></p>
<p><em>Desktop layout</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-61.png" alt="Mobile layout" width="600" height="400" loading="lazy"></p>
<p><em>Mobile layout</em></p>
<h2 id="heading-application-features"><strong>Application Features</strong></h2>
<h3 id="heading-order-book">Order book</h3>
<p>The order book has two sides: the buy side and the sell side.</p>
<p>Both sides contain information about the number of orders opened at each price level.</p>
<p>Each level displays:</p>
<ul>
<li><p><strong>Price</strong>: this is what defines the level. As orders must be placed at a price that is a multiple of the selected market's tick size (0.5), each level will be an increment of 0.5 (as long as there is an order open at that level).</p>
</li>
<li><p><strong>Size</strong>: the total quantity of contracts derived from open orders that have been placed at this level.</p>
</li>
<li><p><strong>Total</strong>: the summed amount of contracts derived from open orders that reside in the book at this level and above. To calculate the total of a given level we take the size of the current level and sum the sizes leading to this price level in the order book. The total is also used to calculate the depth visualizer (colored bars behind the levels). The depth of each level is calculated by taking that level's total as a percentage of the highest total in the book.</p>
</li>
</ul>
<h3 id="heading-grouping-select-box">Grouping Select Box</h3>
<p>By default the orders are grouped by the selected market's ticket size (0.5).</p>
<p>Possible toggling of the grouping is between 0.5, 1, 2.5 for XBTUSD market and 0.05, 0.1 and 0.25 for ETHUSD market.</p>
<p>To group levels, we combine the levels rounded down to the nearest group size – for example, if we change our grouping from 0.5 to 1 then we would combine the data from prices 1000 and 1000.5 and display it under a single level in the order book with the price 1000.</p>
<h3 id="heading-toggle-feed-button">Toggle Feed Button</h3>
<p>This button toggles the selected market between PI_XBTUSD and PI_ETHUSD. These are the two markets we will support -&gt; Bitcoin/USD and Ethereum/USD.</p>
<p>It supports dynamic grouping logic and handles groupings for XBT (0.5, 1, 2.5) and groupings for ETH (0.05, 0.1, 0.25).</p>
<h3 id="heading-kill-feed-button">Kill Feed Button</h3>
<p>Clicking this button stops the feed.</p>
<p>Then clicking this button a second time renews the feed.</p>
<h3 id="heading-status-message">Status Message</h3>
<p>This message will show the currently selected market. It will also show a message saying the feed is killed.</p>
<h2 id="heading-tech-stack-for-our-app">Tech Stack for our App</h2>
<p>Here is a list of the main technologies we will be using:</p>
<ul>
<li><p><a target="_blank" href="https://create-react-app.dev/docs/adding-typescript/">React with TypeScript</a> (<code>yarn create react-app my-app --template typescript</code>) — a UI library we will use for building our application’s user interfaces.</p>
</li>
<li><p><a target="_blank" href="https://redux.js.org/">Redux</a> — a state management library we will use for managing our application’s state.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API">WebSockets</a> — The <code>WebSocket</code> object provides the API for creating and managing a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API">WebSocket</a> connection to a server, as well as for sending and receiving data on the connection. We will use it to implement the logic for consuming the live feeds as well as to be able to stop and renew.</p>
</li>
<li><p><a target="_blank" href="https://www.styled-components.com/docs">styled-components</a> — a CSS-in-JS library that lets you define the CSS styles of your components using ES6 template literals. We will use it to add styles to our app and make the look and feel beautiful. It utilizes tagged template literals to style your components and removes the mapping between components and styles. This means that when you’re defining your styles, you’re actually creating a normal React component that has your styles attached to it.</p>
</li>
<li><p><a target="_blank" href="https://github.com/testing-library/react-testing-library">react-testing-library</a> — The <code>React Testing Library</code> is a very light-weight solution for testing React components. We will use it for testing the UI components of our app.</p>
</li>
<li><p><a target="_blank" href="https://jestjs.io/">Jest</a> - a JavaScript Testing Framework that has become the de facto standard when we talk about testing React applications. We will use it to write some unit tests that will cover the reducer functions we have in our app.</p>
</li>
</ul>
<h2 id="heading-how-to-build-the-app">How to Build the App</h2>
<p>From this point onward I will try to guide you through the process I followed when building this.</p>
<p>💡 I must say that what I am showing you here is just <strong>a way</strong> of creating such an app – but it's not <strong>the way</strong> in any regard. Probably folks with more experience in crypto would do it better.</p>
<h3 id="heading-project-structure">Project Structure</h3>
<p>The project structure is pretty straightforward. We are using React and styled-components, which makes this way of structuring very convenient.</p>
<p>Let's see first what it looks like and then I will explain the what and the why.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-31.png" alt="Project structure" width="600" height="400" loading="lazy"></p>
<p><em>Project structure</em></p>
<p>As you can see on the image above, I have organized most of the components in folders. Each folder contains an <code>index.tsx</code> file, a <code>styles.tsx</code> and a <code>.test.tsx</code> files.</p>
<p><strong>index.tsx</strong> – contains the code responsible for the component logic.</p>
<p><strong>styles.tsx</strong> – contains the code responsible for styling the component. Here is where styled-components shines.</p>
<p><strong>.text.tsx</strong> – these contain the component unit tests.</p>
<p>Let me give you a short summary of the idea behind each of the components in the <code>components</code> folder. Starting top to bottom:</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Button">Button</a> renders a button with a given background color and title. It's used for the two buttons in the footer, <code>Toggle Feed</code> and <code>Kill Feed / Renew Feed</code>.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/DepthVisualizer">DepthVisualizer</a> is the component responsible for drawing the red and the green backgrounds you are seeing behind the numbers. It does this by rendering a row (an HTML <code>div</code> element) with given width, position being left (Bids) or right (Asks).</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Footer">Footer</a> – well, there's not much to say here, it contains the two buttons used in the app.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/GroupingSelectBox">GroupingSelectBox</a> renders the select box we use to change the grouping value, using setGrouping reducer to amend the application state when grouping is being changed.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Header">Header</a> renders the title of the application as well as the GroupingSelectBox component.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Loader">Loader</a> renders loading animation implemented by leveraging <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG">SVG</a>.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/OrderBook">Order Book</a> contains the core logic of the app. Separated components are located in sub-folders, and the Redux state management logic is here also.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Spread">Spread</a> renders the spread value, displayed in the middle of the header (in desktop view). The component itself contains short methods for calculating the amount itself and the percentage value.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/StatusMessage">StatusMessage</a> is a small component used to display <em>status messages.</em> It basically shows which market is currently being displayed and whether the feed is killed.</p>
<h3 id="heading-rendering-performance"><strong>Rendering Performance</strong></h3>
<p>Here is a good moment to talk about <em>rendering performance</em> and <em>inline styling</em> a bit.</p>
<p><strong>Rendering</strong> is the process of React asking your components to describe what they want their section of the UI to look like based on the current combination of props and state.</p>
<p>This process is triggered by a change of the state in your component. This change could be caused by some of the props being changed or by some internal logic of the component.</p>
<p>The point here is that when re-rendering happens unnecessarily, it reduces the performance of our app. This is exactly what happened to me when I introduced the initial implementation of the <em>DepthVisualizer</em> component. It was using styled-components, that is JavaScript, for the drawing part.</p>
<p>In order to solve this, I have changed the component to use inline styles, that is pure CSS, instead of a CSS in JS approach. In other words, my bottleneck was using JavaScript animations, which is a famous reason for reduced performance.</p>
<p>Here is how it looks like now:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> DepthVisualizer: FunctionComponent&lt;DepthVisualizerProps&gt; = <span class="hljs-function">(<span class="hljs-params">{windowWidth, depth, orderType }</span>) =&gt;</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">style</span>=<span class="hljs-string">{{</span>
    <span class="hljs-attr">backgroundColor:</span> `${<span class="hljs-attr">orderType</span> === <span class="hljs-string">OrderType.BIDS</span> ? <span class="hljs-attr">DepthVisualizerColors.BIDS</span> <span class="hljs-attr">:</span> <span class="hljs-attr">DepthVisualizerColors.ASKS</span>}`,
    <span class="hljs-attr">height:</span> "<span class="hljs-attr">1.250em</span>",
    <span class="hljs-attr">width:</span> `${<span class="hljs-attr">depth</span>}%`,
    <span class="hljs-attr">position:</span> "<span class="hljs-attr">relative</span>",
    <span class="hljs-attr">top:</span> <span class="hljs-attr">21</span>,
    <span class="hljs-attr">left:</span> `${<span class="hljs-attr">orderType</span> === <span class="hljs-string">OrderType.BIDS</span> &amp;&amp; <span class="hljs-attr">windowWidth</span> &gt;</span> MOBILE_WIDTH ? `${100 - depth}%` : 0}`,
    marginTop: -24,
    zIndex: 1,
  }} /&gt;</span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DepthVisualizer;
</code></pre>
<p><em>Inline styling</em> is when you write your CSS along with your markup, as values for the <code>style</code> attribute. This is something that is NOT considered a good practice, but as you can see here, there are cases when it's necessary to use it.</p>
<p>💡 Usually you would extract your CSS code into a separate file.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Footer">Footer</a> a simple dummy component used to render the two buttons in the footer of the app.</p>
<p>Dummy components, also known as stateless or representational ones, are components that don't hold state and are usually used just to visualize data in some way. This data is being passed via the props. For example the <code>isFeedKilled</code> flag in the component above.</p>
<p>If such a component needs to execute some kind of interaction, it usually does this by accepting (again via the props, for example <code>toggleFeedCallback</code>) callback functions that can be executed when that interaction happens. For example clicking a button.</p>
<p>On the opposite side we could have smart or state-full components. They are the ones that are connected to the app state and can manipulate it directly. Usually they are the ones that read the data from the state and pass it to the stateless components via their props.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/GroupingSelectBox">GroupingSelectBox</a> contains the Select element you can use to switch between the groupings.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/Header/index.tsx">Header</a> is the header part of the app. It takes care of setting properly the layout consisting of the title 'Order Book' on the left and the select box on the right.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/Loader">Loader</a> is used as an indicator for when the data has not yet been loaded. It leverages a SVG animation I have found online.</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/tree/main/src/components/OrderBook">Order Book</a> is where the real thing is happening. This one consists of a few smaller components:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/d8db0239763dce32fbcae499a6b7deefed9f684f/src/components/OrderBook/styles.tsx#L21">TableContainer</a> – used for styling the views for both the Odds and Bets sides.</p>
</li>
<li><p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/TitleRow/index.tsx">TitleRow</a> – this is the component responsible for displaying the titles of the columns: prize, size, and total, respectively.</p>
</li>
</ul>
<h3 id="heading-how-to-build-the-ui-with-react-and-styled-components">How to Build the UI with React and styled-components</h3>
<p>When we talk about component-based structure, such as the one <a target="_blank" href="https://reactjs.org/">React</a> provides us, the <a target="_blank" href="https://styled-components.com/">styled-components library</a> is likely one of the first choices you might make when styling is needed.</p>
<p>Like <a target="_blank" href="https://www.joshwcomeau.com/">Josh Comeau</a> says in his detailed <a target="_blank" href="https://www.joshwcomeau.com/css/styled-components/">article</a>:</p>
<blockquote>
<p>💡 It's a wonderful tool. In many ways, it's changed how I think about CSS architecture, and has helped me keep my codebase clean and modular, just like React!</p>
</blockquote>
<p>As the name of the lib hints, we could easily style our components by using the <a target="_blank" href="https://reactjs.org/docs/faq-styling.html#what-is-css-in-js">CSS-in-JS pattern</a>. Here is an example of how I used it to write the styles for my <code>Button</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">"styled-components"</span>;

interface ContainerProps {
  <span class="hljs-attr">backgroundColor</span>: string;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Container = styled.button&lt;ContainerProps&gt;<span class="hljs-string">`
  padding: .3em .7em;
  margin: 1em;
  border-radius: 4px;
  border: none;
  color: white;
  background: <span class="hljs-subst">${props =&gt; props.backgroundColor}</span>;
  font-family: "Calibri", sans-serif;
  font-size: 1.2em;

  &amp;:hover {
    cursor: pointer;
    opacity: .8;
  }
`</span>
</code></pre>
<p>Notice how I am using an <code>interface</code> in my styles file, and also the <code>background</code> property being passed as an argument via <code>props</code>. This is part of the CSS-in-JS story.</p>
<p>The possibility to use CSS code in JavaScript or (as someone might say) vice versa comes very handy. For example, when we need a component to look differently depending on something, we can pass through its props a parameter to define this.</p>
<p>As every style is actually a component, this way of writing styles feels a lot like writing React components. I mean, in the end, everything is components, right?</p>
<h3 id="heading-responsiveness-and-page-visibility-detection">Responsiveness and Page Visibility Detection</h3>
<p>While working on this app, I read in several places that, for applications which support rapid updates, is a good practice to implement some kind of mechanism for pausing the whole thing when it is not being used by the user. For example when the user minimizes the browser window or just opens another tab.</p>
<p>Since our Order book is consuming a lot of new chunks of data every second via WSS, I decided to implement such a mechanism as well.</p>
<p>What this does is:</p>
<ul>
<li><p>it shows a loader when the data is not there yet</p>
</li>
<li><p>it changes the meta title to signify that the app is in <code>paused</code> mode</p>
</li>
<li><p>it unpauses the work once the app window is on focus</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-114.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Active mode</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-115.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Paused mode</em></p>
<p>You may see the whole implementation <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/App.tsx">here</a>.</p>
<p>The essential part is in the useEffect hook, which is triggered only once when the application renders for first time.</p>
<p>In there we take advantage of the Page Visibility API by attaching the necessary listeners. And then, in the <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/e74dfad48990ff1a1f12ac45f5a065cc5044ee75/src/App.tsx#L61">handlers</a>, we simply execute the logic we want.</p>
<h3 id="heading-window-size-detection">Window Size Detection</h3>
<p>In almost every app that has some level of responsiveness, you need some logic for detecting the changes in the window size and taking some actions accordingly.</p>
<p>In other words, you need to know when your app is being viewed in certain screen size, so you can arrange your components and adjust your styles so that everything looks nice and in place.</p>
<p>This is especially valid for mobile friendly applications, where responsiveness is essential.</p>
<p>Our implementation of the window size change detection is based on the <code>innerWidtgh</code> property of the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth">browser window object</a> and <code>onresize</code> event that is being triggered when it gets resized.</p>
<p>I am attaching a listener for this event in a <code>useEffect</code> hook in <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/bd24e610e9fc4e271a6820a297b78decf4950fd9/src/App.tsx#L32">App.tsx file</a>. And then, every time the window size changes, I am setting the new width to a state variable via <code>setWindowWidth</code> hook.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [windowWidth, setWindowWidth] = useState(<span class="hljs-number">0</span>);
...
...

<span class="hljs-comment">// Window width detection</span>
useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">window</span>.onresize = <span class="hljs-function">() =&gt;</span> {
    setWindowWidth(<span class="hljs-built_in">window</span>.innerWidth);
  }
  setWindowWidth(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">window</span>.innerWidth);
}, []);
</code></pre>
<p>Then propagate this variable down through all interested components and use it accordingly. For example here is how I use it in <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/index.tsx">Order Book/index.tsx</a> in order to know when and where to render the TitleRow component.</p>
<pre><code class="lang-jsx">{windowWidth &gt; MOBILE_WIDTH &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TitleRow</span> <span class="hljs-attr">windowWidth</span>=<span class="hljs-string">{windowWidth}</span> <span class="hljs-attr">reversedFieldsOrder</span>=<span class="hljs-string">{false}</span> /&gt;</span></span>}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-142.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TitleRow component - desktop view</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-143.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TitleRow component - mobile view</em></p>
<p>Note that it appears on different position depending on that whether you are seeing the app on desktop or mobile.</p>
<p>You may take a look at the <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/TitleRow/index.tsx">component</a> itself and see similar approach of using the window width there.</p>
<h3 id="heading-state-management-with-redux">State Management with Redux</h3>
<p>As you probably guessed already, I used <a target="_blank" href="https://redux.js.org/">Redux</a> for managing the state of the app.</p>
<p>The main logic behind that is concentrated in the <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/orderbookSlice.ts">orderbookSlice</a> reducer. In the following few lines I will walk you through it and see how and why I built it that way.</p>
<p>First we define the interface and the initial state of our order book data. The initial state contains the default values we need to have in place when starting the app.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> interface OrderbookState {
  <span class="hljs-attr">market</span>: string;
  rawBids: number[][];
  bids: number[][];
  maxTotalBids: number;
  rawAsks: number[][];
  asks: number[][];
  maxTotalAsks: number;
  groupingSize: number;
}

<span class="hljs-keyword">const</span> initialState: OrderbookState = {
  <span class="hljs-attr">market</span>: <span class="hljs-string">'PI_XBTUSD'</span>, <span class="hljs-comment">// PI_ETHUSD</span>
  <span class="hljs-attr">rawBids</span>: [],
  <span class="hljs-attr">bids</span>: [],
  <span class="hljs-attr">maxTotalBids</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">rawAsks</span>: [],
  <span class="hljs-attr">asks</span>: [],
  <span class="hljs-attr">maxTotalAsks</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">groupingSize</span>: <span class="hljs-number">0.5</span>
};
</code></pre>
<p>Then there are a few short, self-explanatory methods helping to manipulate the levels data:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> removePriceLevel = (price: number, <span class="hljs-attr">levels</span>: number[][]): number[][] =&gt; levels.filter(<span class="hljs-function"><span class="hljs-params">level</span> =&gt;</span> level[<span class="hljs-number">0</span>] !== price);

<span class="hljs-keyword">const</span> updatePriceLevel = (updatedLevel: number[], <span class="hljs-attr">levels</span>: number[][]): number[][] =&gt; {
  <span class="hljs-keyword">return</span> levels.map(<span class="hljs-function"><span class="hljs-params">level</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (level[<span class="hljs-number">0</span>] === updatedLevel[<span class="hljs-number">0</span>]) {
      level = updatedLevel;
    }
    <span class="hljs-keyword">return</span> level;
  });
};

<span class="hljs-keyword">const</span> levelExists = (deltaLevelPrice: number, <span class="hljs-attr">currentLevels</span>: number[][]): <span class="hljs-function"><span class="hljs-params">boolean</span> =&gt;</span> currentLevels.some(<span class="hljs-function"><span class="hljs-params">level</span> =&gt;</span> level[<span class="hljs-number">0</span>] === deltaLevelPrice);

<span class="hljs-keyword">const</span> addPriceLevel = (deltaLevel: number[], <span class="hljs-attr">levels</span>: number[][]): number[][] =&gt; {
  <span class="hljs-keyword">return</span> [ ...levels, deltaLevel ];
};
</code></pre>
<p>Then the real magic is happening. If the size returned by a delta is 0 then that price level should be removed from the order book. Otherwise you can safely overwrite the state of that price level with new data returned by that delta.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">/** The orders returned by the feed are in the format
 of [price, size][].
 * <span class="hljs-doctag">@param </span>currentLevels Existing price levels - `bids` or `asks`
 * <span class="hljs-doctag">@param </span>orders Update of a price level
 */</span>
<span class="hljs-keyword">const</span> applyDeltas = (currentLevels: number[][], <span class="hljs-attr">orders</span>: number[][]): number[][] =&gt; {
  <span class="hljs-keyword">let</span> updatedLevels: number[][] = currentLevels;

  orders.forEach(<span class="hljs-function">(<span class="hljs-params">deltaLevel</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> deltaLevelPrice = deltaLevel[<span class="hljs-number">0</span>];
    <span class="hljs-keyword">const</span> deltaLevelSize = deltaLevel[<span class="hljs-number">1</span>];

    <span class="hljs-comment">// If new size is zero - delete the price level</span>
    <span class="hljs-keyword">if</span> (deltaLevelSize === <span class="hljs-number">0</span> &amp;&amp; updatedLevels.length &gt; ORDERBOOK_LEVELS) {
      updatedLevels = removePriceLevel(deltaLevelPrice, updatedLevels);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// If the price level exists and the size is not zero, update it</span>
      <span class="hljs-keyword">if</span> (levelExists(deltaLevelPrice, currentLevels)) {
        updatedLevels = updatePriceLevel(deltaLevel, updatedLevels);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// If the price level doesn't exist in the orderbook and there are less than 25 levels, add it</span>
        <span class="hljs-keyword">if</span> (updatedLevels.length &lt; ORDERBOOK_LEVELS) {
          updatedLevels = addPriceLevel(deltaLevel, updatedLevels);
        }
      }
    }
  });

  <span class="hljs-keyword">return</span> updatedLevels;
}
</code></pre>
<p>What follows after these are few helper methods. Let me say a few words about each of them now:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/e74dfad48990ff1a1f12ac45f5a065cc5044ee75/src/components/OrderBook/orderbookSlice.ts#L82">addTotalSums</a> – with the help of this method, we iterate through the orders data, bids or asks, and calculate for each of them the total sum. The total sum value is then used for making the background visualizations.</p>
</li>
<li><p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/e74dfad48990ff1a1f12ac45f5a065cc5044ee75/src/components/OrderBook/orderbookSlice.ts#L99">addDepths</a> – we use this method to calculate the so-called <em>depth</em> for each order. These values will be used later by the depth meter component to display the red and green rows in the background.</p>
</li>
<li><p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/e74dfad48990ff1a1f12ac45f5a065cc5044ee75/src/components/OrderBook/orderbookSlice.ts#L113">getMaxTotalSum</a> – this one returns the max value of all total sums.</p>
</li>
</ul>
<p>Everything below is what we use for creating the application state. As per the <a target="_blank" href="https://redux-toolkit.js.org/rtk-query/overview#create-an-api-slice">Redux Toolkit documentation</a>, it’s using <code>createSlice</code>API to create the <em>slice</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-116.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Redux state</em></p>
<p>Creating a slice requires a string name to identify the slice, an initial state value, and one or more reducer functions to define how the state can be updated.</p>
<p>Once a slice is created, we can export the generated Redux action creators and the reducer function for the whole slice.</p>
<p>The last few lines consist of the exports in question – action creators, state slices selectors and the main reducer.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addBids, addAsks, addExistingState, setGrouping, clearOrdersState } = orderbookSlice.actions;
</code></pre>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectBids = (state: RootState): number[][] =&gt; state.orderbook.bids;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectAsks = (state: RootState): number[][] =&gt; state.orderbook.asks;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectGrouping = (state: RootState): <span class="hljs-function"><span class="hljs-params">number</span> =&gt;</span> state.orderbook.groupingSize;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectMarket = (state: RootState): <span class="hljs-function"><span class="hljs-params">string</span> =&gt;</span> state.orderbook.market;
</code></pre>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> orderbookSlice.reducer;
</code></pre>
<p>With all that, our state manipulation logic is complete. 🎉</p>
<p>Now it’s time to take a look at the protocol we used in our app to take advantage of all these rapid changes in the data we consume.</p>
<h3 id="heading-websocket-protocol-wss">Websocket Protocol (WSS)</h3>
<p>As you may have noticed, we're using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket">Web Socket</a> communication protocol for fetching data into our application. We also use its features, as you will see in a moment, to accomplish other things (such as toggling the feeds and subscribe/unsubscribe from the data channel).</p>
<p><a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/index.tsx">Here</a> is how I used it.</p>
<p>Instead of trying to rely on manual implementation, I used the <a target="_blank" href="https://www.npmjs.com/package/react-use-websocket">react-use-websocket</a> package. It gives you all you need when you want to leverage WSS in a React app. If you want to go into details about this, you may take a look at their <a target="_blank" href="https://github.com/robtaussig/react-use-websocket#readme">documentation</a>.</p>
<h3 id="heading-a-few-words-about-my-implementation">A Few Words About My Implementation</h3>
<p>What we need fist is the endpoint URL where the data feeds are coming from. I am sure there are multiple options out there when we talk about cryptocurrencies. In our app I used the one provided by <a target="_blank" href="http://www.cryptofacilities.com/">www.cryptofacilities.com/</a>.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> WSS_FEED_URL: string = <span class="hljs-string">'wss://www.cryptofacilities.com/ws/v1'</span>;
</code></pre>
<p>Then the only thing we need to do to start consuming the data is to put the <code>useWebSocket</code> hook to work. As you may have guessed already, this hook is provided by the package mentioned above.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> useWebSocket <span class="hljs-keyword">from</span> [<span class="hljs-string">"react-use-websocket"</span>](<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">https:</span>//<span class="hljs-attr">github.com</span>/<span class="hljs-attr">robtaussig</span>/<span class="hljs-attr">react-use-websocket</span>&gt;</span></span>);

...
...
...

const { sendJsonMessage, getWebSocket } = useWebSocket(WSS_FEED_URL, {
    <span class="hljs-attr">onOpen</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'WebSocket connection opened.'</span>),
    <span class="hljs-attr">onClose</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'WebSocket connection closed.'</span>),
    <span class="hljs-attr">shouldReconnect</span>: <span class="hljs-function">(<span class="hljs-params">closeEvent</span>) =&gt;</span> <span class="hljs-literal">true</span>,
    <span class="hljs-attr">onMessage</span>: <span class="hljs-function">(<span class="hljs-params">event: WebSocketEventMap[<span class="hljs-string">'message'</span>]</span>) =&gt;</span>  processMessages(event)
  });
</code></pre>
<p>We pass the endpoint as the first argument and a few callback functions after that. These help us perform certain actions when one of the following happens:</p>
<ul>
<li><p><code>onOpen</code> – what to do when WebSocket connection is established.</p>
</li>
<li><p><code>onClose</code> – what to do when WebSocket connection is terminated.</p>
</li>
<li><p><code>shouldReconnect</code> – this is just a flag, saying if we want automatic reconnect when the connection drops for some reason.</p>
</li>
<li><p><code>onMessage</code> – this is the main event that brings us the chunks with the data (I call <code>processMessage</code> method every time when that happens. This means that every time when a new chunk of data is received, we process it and display it respectively).</p>
</li>
</ul>
<p>Down below is the method in question. It simply does two things:</p>
<ul>
<li><p>Either calls a method called <code>process</code> (No pun intended 😄) – this method is called every time new data for bids or asks is received and it processes it accordingly.</p>
</li>
<li><p>Dispatches an event that is using one of the <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/e74dfad48990ff1a1f12ac45f5a065cc5044ee75/src/components/OrderBook/orderbookSlice.ts#L148">reducer functions</a> we have seen earlier. This function practically creates the initial state of our application.</p>
</li>
</ul>
<p>In order to decide whether we are adding data to the current state or we should initialize it, we check for a property called <code>numLevels</code>. This is something that comes from the API, the very first time we establish the WebSocket connection.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-117.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Initial payload</em></p>
<p>The rest of the code you see in this <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/index.tsx">file</a> is mostly for preparing and rendering the results on the screen.</p>
<p>The most interesting part would be the method <code>buildPriceLevels</code> that is used for both halves – bids and asks. It sorts the data, makes the necessary calculations, and passes it to the relevant components for visualizing it. Those are <code>DepthVisualizer</code> and <code>PriceLevelRow</code> I mentioned earlier in this article.</p>
<h2 id="heading-grouping">Grouping</h2>
<p>The grouping is an important part of how the order book works, as it defines by what ticket size the orders are grouped.</p>
<p>In our application, I have implemented a toggling functionality per each market, that allows grouping it as follows:</p>
<ul>
<li>Between 0.5, 1, 2.5 for XBTUSD market.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-118.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>XBTUSD market grouping</em></p>
<ul>
<li>Between 0.05, 0.1 and 0.25 for ETHUSD market.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-119.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>ETHUSD market grouping</em></p>
<p>There is a short gist I created when trying to figure out how to implement the grouping logic. You may find it <a target="_blank" href="https://gist.github.com/mihailgaberov/5faa2c1c3e4fd3e0593ad68861b989ce">here</a>.</p>
<p>Also, aside from that gist, while developing this I have performed more than a few experiments out of the project itself. And just because these are just local files on my computer, I will publish them here for those of you who are even more curious.</p>
<p>It’s a small side npm project that has only one dependency. Here is the package.json file:</p>
<pre><code class="lang-jsx">{
  <span class="hljs-string">"name"</span>: <span class="hljs-string">"grouping"</span>,
  <span class="hljs-string">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-string">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-string">"license"</span>: <span class="hljs-string">"MIT"</span>,
  <span class="hljs-string">"dependencies"</span>: {
    <span class="hljs-string">"lodash.groupby"</span>: <span class="hljs-string">"^4.6.0"</span>
  }
}
</code></pre>
<p>And here is the code itself:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> bids = [
    [
        <span class="hljs-number">50163</span>,
        <span class="hljs-number">110</span>
    ],
    [
        <span class="hljs-number">50162</span>,
        <span class="hljs-number">13140</span>
    ],
    [
        <span class="hljs-number">50158</span>,
        <span class="hljs-number">3763</span>
    ],
    [
        <span class="hljs-number">50156</span>,
        <span class="hljs-number">1570</span>
    ],
    [
        <span class="hljs-number">50155</span>,
        <span class="hljs-number">21997</span>
    ],
    [
        <span class="hljs-number">50152.5</span>,
        <span class="hljs-number">450</span>
    ],
    [
        <span class="hljs-number">50151</span>,
        <span class="hljs-number">4669</span>
    ],
    [
        <span class="hljs-number">50150.5</span>,
        <span class="hljs-number">10329</span>
    ],
    [
        <span class="hljs-number">50150</span>,
        <span class="hljs-number">2500</span>
    ],
    [
        <span class="hljs-number">50149.5</span>,
        <span class="hljs-number">450</span>
    ],
    [
        <span class="hljs-number">50149</span>,
        <span class="hljs-number">4022</span>
    ],
    [
        <span class="hljs-number">50148</span>,
        <span class="hljs-number">20000</span>
    ],
    [
        <span class="hljs-number">50147</span>,
        <span class="hljs-number">5166</span>
    ],
    [
        <span class="hljs-number">50146.5</span>,
        <span class="hljs-number">5274</span>
    ],
    [
        <span class="hljs-number">50145</span>,
        <span class="hljs-number">174609</span>
    ],
    [
        <span class="hljs-number">50143</span>,
        <span class="hljs-number">20000</span>
    ],
    [
        <span class="hljs-number">50141</span>,
        <span class="hljs-number">28000</span>
    ],
    [
        <span class="hljs-number">50140.5</span>,
        <span class="hljs-number">5000</span>
    ],
    [
        <span class="hljs-number">50138</span>,
        <span class="hljs-number">6000</span>
    ],
    [
        <span class="hljs-number">50132.5</span>,
        <span class="hljs-number">4529</span>
    ],
    [
        <span class="hljs-number">50132</span>,
        <span class="hljs-number">4755</span>
    ],
    [
        <span class="hljs-number">50131</span>,
        <span class="hljs-number">12483</span>
    ],
    [
        <span class="hljs-number">50128.5</span>,
        <span class="hljs-number">61115</span>
    ],
    [
        <span class="hljs-number">50128</span>,
        <span class="hljs-number">23064</span>
    ],
    [
        <span class="hljs-number">50125.5</span>,
        <span class="hljs-number">181363</span>
    ]
]

<span class="hljs-comment">/* function roundDownNearest(num, acc) {
    if (acc &lt; 0) {
        return Math.floor(num * acc) / acc;
    } else {
        return Math.floor(num / acc) * acc;
    }
} */</span>

<span class="hljs-comment">/* function groupByTicketSize(ticketSize, levels) {
    const result = levels.map((element, idx) =&gt; {
        const nextLevel = levels[idx + 1];

        if (nextLevel) {
            const currentPrice = element[0];
            const currentSize = element[1];
            const nextPrice = nextLevel[0];
            const nextSize = nextLevel[1];
            console.log("current level: ", element)
            console.log("next level: ", nextLevel)

            element[0] = roundDownNearest(currentPrice, ticketSize);

            if (currentPrice - nextPrice &lt; ticketSize) {
                element[1] = currentSize + nextSize;
            }
            console.log("==================================&gt; Result: ", element)

            return element;
        }

    }).filter(Boolean); 


    console.log("============================================================");
    console.log(result)
} */</span>

<span class="hljs-keyword">const</span> test = [
    [<span class="hljs-number">1004.5</span>, <span class="hljs-number">1</span>],
    [<span class="hljs-number">1001.5</span>, <span class="hljs-number">1</span>],
    [<span class="hljs-number">1001</span>,   <span class="hljs-number">1</span>],
    [<span class="hljs-number">1000.5</span>, <span class="hljs-number">1</span>],
    [<span class="hljs-number">1000</span>,   <span class="hljs-number">1</span>],
    [<span class="hljs-number">999.5</span>,  <span class="hljs-number">1</span>],
    [<span class="hljs-number">999</span>,    <span class="hljs-number">1</span>],
    [<span class="hljs-number">990</span>,    <span class="hljs-number">1</span>],
    [<span class="hljs-number">988</span>,    <span class="hljs-number">1</span>]
]

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">groupByTicketSize</span>(<span class="hljs-params">ticketSize, levels</span>) </span>{
    <span class="hljs-keyword">const</span> result = [];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; levels.length; i++) {
        <span class="hljs-built_in">console</span>.log(levels[i])
        <span class="hljs-keyword">const</span> prevLevel = levels[i<span class="hljs-number">-1</span>]
        <span class="hljs-keyword">const</span> level1 = levels[i]
        <span class="hljs-keyword">const</span> level2 = levels[i+<span class="hljs-number">1</span>]

        <span class="hljs-keyword">if</span> (prevLevel &amp;&amp; level1 &amp;&amp; level1[<span class="hljs-number">0</span>] - ticketSize === prevLevel) <span class="hljs-keyword">return</span>

        <span class="hljs-keyword">if</span> (level2 &amp;&amp; level1[<span class="hljs-number">0</span>] - level2[<span class="hljs-number">0</span>] &lt; ticketSize) {
            <span class="hljs-keyword">const</span> newLevel = [level2[<span class="hljs-number">0</span>], level1[<span class="hljs-number">1</span>] + level2[<span class="hljs-number">1</span>]];
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"newLevel"</span>, newLevel)
            result.push(newLevel);
        } <span class="hljs-keyword">else</span> {
            result.push(level1)
        }
    }

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"============================================================"</span>);
    <span class="hljs-built_in">console</span>.log(result)
}

<span class="hljs-comment">// groupByTicketSize(1, bids);</span>
groupByTicketSize(<span class="hljs-number">1</span>, test);
</code></pre>
<h2 id="heading-how-to-perform-unit-tests-on-the-app">How to Perform Unit Tests on the App</h2>
<p>For performing unit testing I used the <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro/">react-testing-library</a>.</p>
<p>The main idea behind it that the developer should write tests only for what the user will see and interact with. There is no much point of testing implementation details.</p>
<p>💡 Imagine, just to give you an example, that you have implemented a list component that is just displaying lines of textual data. Say something like a todo list.</p>
<p>Then imagine that this data is coming from an API call in the shape of array. A data structure that you could easily iterate through via various methods – some sort of a loop cycle, such as for() or while(). Or you could use another more functional approach, say .map() method.</p>
<p>Now ask yourself – for the end user, the one that will just see the listed text data, does your implementation matter? As long as everything works as expected and in a good, performant way, the answer is ‘no, it does not’.</p>
<p>This is what your tests should reflect.</p>
<p>In the context of our Order Book application, each test file is located in the same directory as the implementation file. Most of the tests are short and self-explanatory, due to the fact that these are testing mostly rendering logic and only the <a target="_blank" href="https://en.wikipedia.org/wiki/Happy_path">happy path</a>.</p>
<p>For example let’s take a look at the button component tests below:</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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./index'</span>;

test(<span class="hljs-string">'renders button with title'</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">backgroundColor</span>=<span class="hljs-string">{</span>'<span class="hljs-attr">red</span>'} <span class="hljs-attr">callback</span>=<span class="hljs-string">{jest.fn}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{</span>'<span class="hljs-attr">Toggle</span>'} /&gt;</span></span>);
  <span class="hljs-keyword">const</span> btnElement = screen.getByText(<span class="hljs-regexp">/Toggle/i</span>);
  expect(btnElement).toBeInTheDocument();
});
</code></pre>
<p>It just verifies that the component is rendered properly and it displays what we expect the user to see. Which is the title <em>Toggle</em> in this case.</p>
<p>For testing the <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/src/components/OrderBook/orderbookSlice.test.ts">reducers</a> I have used <a target="_blank" href="https://jestjs.io/">Jest</a>, as this is the only not visual part that we'll cover. These tests are also pretty simple and self-explanatory. I use them for testing whether the initial application state is in place and to see that adding price levels to that state works correctly.</p>
<h2 id="heading-how-to-deploy-the-app-to-vercel">How to Deploy the App to Vercel</h2>
<p>Finally – deployment time. 🎉</p>
<p>After finishing the development and testing our application, let’s put it live.</p>
<p>I used the <a target="_blank" href="https://vercel.com/">Vercel</a> platform for this purpose. They offer a pretty rich and easy to use interface as well as integrations for all famous source control platforms out there – including, of course, GitHub (where our application repo lives).</p>
<p>Assuming you have a GitHub account, what you need to do if you want to deploy it on your own is to login with it <a target="_blank" href="https://vercel.com/login">here</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-120.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Vercel login screen</em></p>
<p>Click on the <em>+New Project</em> button in the top right corner. Then import your Git repository using the provided options in the screen that opens. Here is how mine looks:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-121.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Vercel Import Git Repository screen</em></p>
<p>After importing the project, you will be able to do the actual deploy. When finished, Vercel will generate URLs for you to access your newly deployed app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-122.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Vercel production deployment screen</em></p>
<p>And I think you will receive an email letting you know if your deployment was successful. That email also contains these URLs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-123.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Vercel successful deployment email</em></p>
<p>Congratulations! 👏🏻</p>
<p>You now have your own <a target="_blank" href="https://orderbook-mihailgaberov.vercel.app/">Order Book application</a> up and running online.</p>
<h2 id="heading-how-to-add-a-build-badge-on-github">How to Add a Build Badge on GitHub</h2>
<p>This is not order book related, but I decided to share it with you here anyway. It’s about those small details that make the big picture somehow more complete and attractive.</p>
<p>Maybe some of you have wondered how can you get one of these so called <em>badges</em>?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-124.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here is the answer: <a target="_blank" href="https://shields.io/">https://shields.io/</a>.</p>
<p>You go to the <a target="_blank" href="https://shields.io/category/other">Other section</a> and find the GitHub Deployments option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-125.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then click on it and follow the instructions.</p>
<p>There is one more thing you need to do in order to have this fully functioning. You go to your GitHub repository → <a target="_blank" href="https://github.com/mihailgaberov/orderbook/actions">Actions</a> tab and create new workflow file. You may just go ahead and copy the content of <a target="_blank" href="https://github.com/mihailgaberov/orderbook/actions/runs/2143399541/workflow">mine from here</a>. Name it <em>main.yml</em>.</p>
<p>What this will do is run the jobs defined in that file. In our case this is just the build job which is basically spinning a new build and running the tests.</p>
<p>After completing this, you just need add the following lines to your <a target="_blank" href="https://github.com/mihailgaberov/orderbook/blob/main/README.md">README</a> file:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-comment">&lt;!-- prettier-ignore-start --&gt;</span></span>
[<span class="hljs-string">![Tests</span>](<span class="hljs-link">&lt;https://github.com/mihailgaberov/orderbook/actions/workflows/main.yml/badge.svg&gt;</span>)](<span class="hljs-link">&lt;https://github.com/mihailgaberov/orderbook/actions/workflows/main.yml&gt;</span>)
[<span class="hljs-string">![Build Status</span>][<span class="hljs-symbol">build-badge</span>]][<span class="hljs-symbol">build</span>]

[<span class="hljs-symbol">build-badge</span>]: <span class="hljs-link">&lt;https://img.shields.io/github/deployments/mihailgaberov/orderbook/production?label=vercel&amp;logoColor=vercel&gt;</span>
[<span class="hljs-symbol">build</span>]: <span class="hljs-link">&lt;https://github.com/mihailgaberov/orderbook/deployments&gt;</span>
<span class="xml"><span class="hljs-comment">&lt;!-- prettier-ignore-end --&gt;</span></span>
</code></pre>
<p>💡 Don’t forget to put your own details in the URLs, that is your GitHub username and the name of your repository.</p>
<p>After pushing these changes you should see the badges displayed on your README: 🥳.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-126.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>GitHub badges</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>If you are reading this from the beginning, I will name you a champion. 🍾</p>
<p>It has been a long trip, but hopefully interesting and fun to walk along with me!</p>
<p>Now it’s time to summarize what we have done here and try to extract some useful insights which will help us in our future development challenges.</p>
<p>I will layout below my opinion of what was the most challenging in building this application. And I will be even more eager to find out what is yours.</p>
<h3 id="heading-rendering-performance-1">Rendering Performance</h3>
<p>This really bit me in the beginning, when I was building the UI and was trying to implement the drawing of the price level rows.</p>
<p>I mentioned earlier how I have managed to solve it and I think this is going to be something I will remember for sure.</p>
<h3 id="heading-grouping-functionality">Grouping Functionality</h3>
<p>Implementing this was also kind of challenging because there were several factors I had to take into account. Because of the market we are in and the range I had to do the calculations in.</p>
<p>It took me a while to polish it (remember the side mini project and the gist I shared in the previous sections) and I still think it could be improved even more. Try switching between the markets and the grouping values multiple times and observe the results.</p>
<h3 id="heading-space-for-improvement">Space for Improvement</h3>
<p>One thing already mentioned is for sure the grouping. Which should also improve the visualizing of the red and green parts – they (almost) always should form a not ideal triangle.</p>
<p>If we try to look at the bigger picture, this order book application can be a part of a dashboard screen filled with other widgets as well, and they all can interact between them.</p>
<p>For example, changing the grouping of the order book to reflect on changing the views in the other widgets as well – say showing a market chart like this one below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-127.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>I am not even mentioning adding new markets as an <em>improvement</em>, as it’s kinda clear. But this should be taken into account when building the functionality for the current markets, as to do it in a way that will be easily extendable. So that adding a new market to the order book be a trivial and quick task to do.</p>
<p>I think that's all from me.</p>
<p>Thanks for reading! 🙏</p>
<h2 id="heading-references">References</h2>
<p>Here are few links you might find useful to read:</p>
<p><a target="_blank" href="https://www.joshwcomeau.com/css/styled-components/">The styled-components Happy Path</a></p>
<p><a target="_blank" href="https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/#what-is-rendering">Blogged Answers: A (Mostly) Complete Guide to React Rendering Behavior</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Manage State in a React App – With Hooks, Redux, and More ]]>
                </title>
                <description>
                    <![CDATA[ Hi! In this article we'll take a look at the many ways you can manage state in a React app. We'll start by talking about what state is, and then go through the many tools you can use to manage it. We'll look at the simple useState hook and also ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-manage-state-in-a-react-app/</link>
                <guid isPermaLink="false">66d45f02d1ffc3d3eb89ddeb</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 21 Mar 2022 23:31:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/lautaro-andreani-UYsBCu9RP3Y-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi! In this article we'll take a look at the many ways you can manage state in a React app.</p>
<p>We'll start by talking about what state is, and then go through the many tools you can use to manage it.</p>
<p>We'll look at the simple useState hook and also learn about more complex libraries like Redux. Then we'll check out the most recent options available like Recoil and Zustand.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-state-in-react">What is State in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-usestate-hook">How to Use the UseState Hook</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-use-useeffect-to-read-state-updates">How to Use useEffect to Read State Updates</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-pass-a-callback-to-state-update-function">How to Pass a Callback to State Update Function</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-managing-scale-and-complexity">Managing scale and complexity</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-react-context">React context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-usereducer-hook">How to Use the UseReducer Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-about-redux">What About Redux?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-alternatives-to-redux">Alternatives to Redux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-redux-toolkit">Redux toolkit</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-a-mention-for-redux-thunk-and-redux-saga">A mention for Redux Thunk and Redux Saga</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-recoil">Recoil</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-jotai">Jotai</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-zustand">Zustand</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h1 id="heading-what-is-state-in-react">What is state in React?</h1>
<p>In modern React, we build our applications with <strong>functional components</strong>. Components are themselves JavaScript functions, independent and <strong>reusable</strong> bits of code.</p>
<p>The purpose of building the application with components is to have a modular architecture, with a clear separation of concerns. This makes code easier to understand, easier to maintain, and easier to reuse when possible.</p>
<p>The <strong>state is an object that holds information</strong> about a certain component. Plain JavaScript functions don't have the ability to store information. The code within them executes and "dissapears" once the execution is finished.</p>
<p>But thanks to state, React functional components can store information even after execution. When we need a component to store or "remember" something, or to act in a different way depending on the environment, state is what we need to make it work this way.</p>
<p>It's important to mention that not all components in a React app must have state. There are stateless components as well which just render its content without the need to store any information, and that's just fine.</p>
<p>Another important thing to mention is that state change is one of the two things that make a React component re-render (the other is a change in props). In this way, the state stores information about the component and also controls its behavior.</p>
<h1 id="heading-how-to-use-the-usestate-hook">How to Use the UseState Hook</h1>
<p>In order to implement state in our components, React provides us with a hook called <strong>useState</strong>. Let's see how it works with the following example.</p>
<p>We'll use the classic counter example, in which we're displaying a number and we have several buttons to increase, decrease, or reset that number.</p>
<p>This is a good example of an app where we need to store a piece of information and render something different every time that information changes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/5bueYQblr--2-.gif" alt="5bueYQblr--2-" width="600" height="400" loading="lazy"></p>
<p>The code for this app looks like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> { useState } <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">App</span>(<span class="hljs-params"></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> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count+1)}&gt;Add 1<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;Decrease 1<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+10)}&gt;Add 10<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-10)}&gt;Decrease 10<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(0)}&gt;Reset count<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> App
</code></pre>
<ul>
<li><p>First we import the hook from React: <code>import { useState } from 'react'</code></p>
</li>
<li><p>Then we initialize the state: <code>const [count, setCount] = useState(0)</code></p>
</li>
</ul>
<p>Here we provide a variable name for the state (<code>count</code>) and a function name we'll use every time we need to update that state (<code>setCount</code>). Last, we set the initial value of the state (<code>0</code>), which will be the value loaded by default every time the app starts.</p>
<ul>
<li>Lastly, as mentioned above, every time we want to update the state we have to use the function we declared: <code>setCount</code> To use it, we just need to call it passing it the new state we want as a parameter. That is, if we want to add 1 to the previous estate, we call <code>setCount(count+1)</code>.</li>
</ul>
<p>As mentioned too, this will cause an update of the state and hence the re-render of the component. Which in our app means we'll see on the screen that the counter going up.</p>
<h2 id="heading-how-to-use-useeffect-to-read-state-updates">How to Use useEffect to Read State Updates</h2>
<p>It's important to mention that the setState function is <strong>asynchronous</strong>. So if we try to read the state immediately after updating it, like this:</p>
<pre><code class="lang-js">&lt;button onClick={<span class="hljs-function">() =&gt;</span> {
          setCount(count+<span class="hljs-number">1</span>)
          <span class="hljs-built_in">console</span>.log(count)
}}&gt;Add <span class="hljs-number">1</span>&lt;/button&gt;
</code></pre>
<p>we would get the previous value of the state, without the update.</p>
<p>The correct way of reading state after the update would be using the <strong>useEffect</strong> hook. It lets us execute a function after every component re-render (by default) or after any particular variable we declare changes.</p>
<p>Something like this:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(value), [value])
</code></pre>
<h2 id="heading-how-to-pass-a-callback-to-state-update-function">How to Pass a Callback to State Update Function</h2>
<p>Also, the fact that useState is asynchronous has implications when considering very frequent and quick state changes.</p>
<p>Take, for example, the case of a user that presses the ADD button many times in a row, or a loop that emits a click event a certain number of times.</p>
<p>By updating state like <code>setCount(count+1)</code> we take the risk that <code>count</code> won't yet be updated when the next event is fired.</p>
<p>For example, let's say at the start <code>count = 0</code>. Then <code>setCount(count+1)</code> is called and the state is asynchronously updated. But then again <code>setCount(count+1)</code> is called, before the state update was completed. This means that still <code>count = 0</code>, which means that the second <code>setCount</code> won't update the state correctly.</p>
<p>A more defensive approach would be to pass <code>setCount</code> a callback, like so: <code>setCount(prevCount =&gt; prevCount+1)</code></p>
<p>This makes sure that the value to update is the most recent one and keeps us away from the problem mentioned above. Every time we perform updates on a previous state we should use this approach.</p>
<h1 id="heading-managing-scale-and-complexity">Managing Scale and Complexity</h1>
<p>So far, state management seems a piece of cake. We just need a hook, a value, and a function to update it, and we're ready to go.</p>
<p>But once apps start to get bigger and more complex, using only this may start to cause some problems.</p>
<h2 id="heading-react-context">React context</h2>
<p>The first problem that may occur is when we have a lot of nested components, and we need many "sibling" components to share the same state.</p>
<p>The obvious answer here is to "lift" the state up, meaning that a parent component will be the one to hold the state and it will pass it as props to the children components.</p>
<p>This works just fine, but when we have a lot of nested components, we may need to pass props through many component levels. This is known as <strong>"prop drilling"</strong> and not only looks ugly but also creates code that's hard to maintain.</p>
<p>Prop drilling can also cause <strong>unnecessary re-renders</strong> which can affect the performance of our app. If between our parent component (which stores the state) and our children components (which consume the state) there are other components ("middle components"), we will need to pass props through these middle components too, even if they don't need the prop.</p>
<p>This means that these "middle components" will re-render when the prop changes, even if they have nothing different to render.</p>
<p>A solution to this is to use <strong>React context</strong>, which in short is a way to create a wrapper component that wraps around any group of components we want and can pass props directly to those components, without the need to "drill" through components that wont necessarily use that state.</p>
<p>The thing to watch when using context is that when the context state changes, all the wrapped components that receive that state will re-render. And this might not be necessary depending on the case and might cause performance issues, too.</p>
<p>So it's always important to balance whether we really need to make a state available to many components or whether we can just keep it local in a single component. And if we need to make it available to many components, is it really a good idea to put it in context or can we just lift it up a level.</p>
<p>Kent C Dodds has a <a target="_blank" href="https://kentcdodds.com/blog/application-state-management-with-react">cool article</a> on this topic.</p>
<h2 id="heading-how-to-use-the-usereducer-hook">How to Use the UseReducer Hook</h2>
<p>Another problem may come up when you're using useState where the new state to be set depends on the previous state (like our count example) or when state changes occur very frequently in our application.</p>
<p>In these occasions, useState may provoke some unexpected and unpredictable behavior. In come <strong>reducers</strong> to solve this problem.</p>
<p>A <strong>reducer</strong> is a pure function that takes the previous state and an action as an argument, and returns the next state. It's called a reducer because it's the same function type you could pass to an array: <code>Array.prototype.reduce(reducer, initialValue)</code>.</p>
<p><strong>useReducer</strong> is the hook Reacts provides that lets us implement reducers to manage our state. Using this hook, our previous example app would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> { useReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</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-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
    <span class="hljs-keyword">switch</span> (action.type) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD'</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">'SUB'</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">'ADD10'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">10</span> }
      <span class="hljs-keyword">case</span> <span class="hljs-string">'SUB10'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">10</span> }
      <span class="hljs-keyword">case</span> <span class="hljs-string">'RESET'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }
      <span class="hljs-attr">default</span>: <span class="hljs-keyword">return</span> state
    }
  }

  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, { <span class="hljs-attr">count</span>: <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">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count is: {state.count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch({type: 'ADD'})}&gt;Add 1<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: 'SUB'})}&gt;Decrease 1<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: 'ADD10'})}&gt;Add 10<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: 'SUB10'})}&gt;Decrease 10<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: 'RESET'})}&gt;Reset count<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> App
</code></pre>
<ul>
<li><p>Again we start by importing the hook from React: <code>import { useReducer } from 'react'</code></p>
</li>
<li><p>Then we'll declare a reducer function, which as parameters will take the current state and an action to perform on it. Within it, it will have a switch statement that will read the action type, execute the corresponding action on the state, and return the updated state.</p>
</li>
</ul>
<blockquote>
<p>It's common practice to use switch statements on reducers and capital letters to declare the actions. ;)</p>
</blockquote>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
    <span class="hljs-keyword">switch</span> (action.type) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD'</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">'SUB'</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">'ADD10'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">10</span> }
      <span class="hljs-keyword">case</span> <span class="hljs-string">'SUB10'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">10</span> }
      <span class="hljs-keyword">case</span> <span class="hljs-string">'RESET'</span>: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }
      <span class="hljs-attr">default</span>: <span class="hljs-keyword">return</span> state
    }
  }
</code></pre>
<ul>
<li>Afterwards, it's time to declare our <strong>useReducer</strong> hook, which looks fairly similar to the useState hook. We declare a <strong>value for our state</strong> ('state' in our case), a <strong>function we'll use to modify it</strong> ('dispatch'), and then useReducer will take the <strong>reducer function</strong> as first parameter and the <strong>default state</strong> as second parameter.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> })
</code></pre>
<ul>
<li>Lastly, to update our state we won't call the reducer directly, but instead we'll call the function we just created ('dispatch'), passing it the corresponding action type we want to execute. Behind the scenes, the dispatch function will connect with the reducer and actually modify the state.</li>
</ul>
<pre><code class="lang-js">&lt;button onClick={<span class="hljs-function">() =&gt;</span> dispatch({<span class="hljs-attr">type</span>: <span class="hljs-string">'ADD'</span>})}&gt;Add <span class="hljs-number">1</span>&lt;/button&gt;
</code></pre>
<p>It's quite a bit more boilerplate than using useState, but useReducer isn't that complex after all.</p>
<p>To sum it up, we just need:</p>
<ul>
<li><p>A reducer, that is the function that will consolidate all possible state changes</p>
</li>
<li><p>A dispatch function, that will send the modifying actions to the reducer.</p>
</li>
</ul>
<p>The thing here is that the UI elements won't be able to update the state directly like they did before when calling setState with a value. Now they will have to call an action type and go through the reducer, which makes state management more modular and predictable. ;)</p>
<h2 id="heading-what-about-redux">What About Redux?</h2>
<p><a target="_blank" href="https://redux.js.org/">Redux</a> is a library that has been around for a long time and is widely used in the React environment.</p>
<p>Redux is a tool that comes to solve both of the problems mentioned before (prop drilling and unpredictable state behavior on frequent and complex state changes).</p>
<p>It's important to mention that Redux is an agnostic library, meaning it can be implemented on any front end app, not just React.</p>
<p>The Redux set of tools is very similar to what we've just seen with useReducer, but with a few more things. There are three main building blocks in Redux:</p>
<ul>
<li><p><strong>A store</strong> — an object that holds the app state data</p>
</li>
<li><p><strong>A reducer</strong> — a function that returns some state data, triggered by an action type</p>
</li>
<li><p><strong>An action</strong> — an object that tells the reducer how to change the state. It must contain a type property, and it can contain an optional payload property</p>
</li>
</ul>
<p>Implementing Redux, our example app would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</span>

<span class="hljs-keyword">import</span> { Provider, useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>
<span class="hljs-keyword">import</span> { addOne, subOne, addSome, subSome, reset } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/actions/count.actions'</span>

<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">'./store'</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> dispatch = useDispatch()
  <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">return</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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(addOne())}&gt;Add 1<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(subOne())}&gt;Decrease 1<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(addSome(10))}&gt;Add 10<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(subSome(10))}&gt;Decrease 10<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(reset())}&gt;Reset count<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 class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Besides, we now would need a new <strong>store</strong> directory, with its corresponding store, reducer, and actions files.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Cbdp2DJY9.png" alt="Cbdp2DJY9" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-js"><span class="hljs-comment">// index.js (STORE)</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> CountReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers/count.reducer'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> createStore(CountReducer)
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// count.reducer.js</span>
<span class="hljs-keyword">import</span> { ADD, SUB, ADDSOME, SUBSOME, RESET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../actions/count.actions'</span>

<span class="hljs-keyword">const</span> CountReducer = <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> ADD: <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> SUB: <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> ADDSOME: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + action.payload }
      <span class="hljs-keyword">case</span> SUBSOME: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - action.payload }
      <span class="hljs-keyword">case</span> RESET: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }
      <span class="hljs-attr">default</span>: <span class="hljs-keyword">return</span> state
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CountReducer
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// count.actions.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD = <span class="hljs-string">'ADD'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addOne = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: ADD })

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADDSOME = <span class="hljs-string">'ADDSOME'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addSome = <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> ({
    <span class="hljs-attr">type</span>: ADDSOME,
    <span class="hljs-attr">payload</span>: value
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SUBSOME = <span class="hljs-string">'SUBSOME'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> subSome = <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> ({
    <span class="hljs-attr">type</span>: SUBSOME,
    <span class="hljs-attr">payload</span>: value
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RESET = <span class="hljs-string">'RESET'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> reset = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: RESET })
</code></pre>
<p>This is a lot more boilerplate that what we've seen before (that's what Redux is mainly criticized for), so let's break it down into pieces:</p>
<ul>
<li><p>As I mentioned, Redux is an external library, so before anything we need to install it by running <code>npm i redux react-redux</code>. <code>redux</code> will bring the core functions we need to manage our state and <code>react-redux</code> will install some cool hooks to easily read and modify state from our components.</p>
</li>
<li><p>Now, first thing is the <strong>store</strong>. In Redux the store is the entity that has all the app state information. Thanks to Redux, we'll be able to access the store from any component we want (just like with context).</p>
</li>
</ul>
<p>To create a store, we import the <code>createStore</code> function and pass it a reducer as input.</p>
<p>Know that you can also combine different reducers and pass it to the same store in case you'd like to separate concerns into different reducers.</p>
<pre><code class="lang-js"><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> CountReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducers/count.reducer'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> createStore(CountReducer)
</code></pre>
<ul>
<li>Then there's the <strong>reducer</strong>, which works exactly the same as the one we've seen with useReducer. It takes the default state and an action as parameters, then within it it has a switch statement to read the action type, execute the corresponding state modification, and return the updated state.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { ADD, SUB, ADDSOME, SUBSOME, RESET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../actions/count.actions'</span>

<span class="hljs-keyword">const</span> CountReducer = <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> ADD: <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> SUB: <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> ADDSOME: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count + action.payload }
      <span class="hljs-keyword">case</span> SUBSOME: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: state.count - action.payload }
      <span class="hljs-keyword">case</span> RESET: <span class="hljs-keyword">return</span> { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }
      <span class="hljs-attr">default</span>: <span class="hljs-keyword">return</span> state
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CountReducer
</code></pre>
<ul>
<li>Then come the <strong>actions</strong>. Actions are what we're going to use to tell the reducer how to update the state. In the code you can see that for each action we're declaring constants to use them instead of plain strings (this is a good practice to improve maintainability), and functions that return either just a type or a type and a payload. These functions are what we're going to dispatch from our component in order to change the state. ;)</li>
</ul>
<p>Note that I changed the example a bit in order to show what payload means when talking about actions. In case we want to <strong>pass a parameter from the component</strong> when we dispatch an action, <strong>payload is where that information will be</strong>.</p>
<p>In the example, you can see that we can now pass directly from the component the number we want to add/substract when we call ADDSOME/SUBSOME.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD = <span class="hljs-string">'ADD'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addOne = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: ADD })

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADDSOME = <span class="hljs-string">'ADDSOME'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addSome = <span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> ({
    <span class="hljs-attr">type</span>: ADDSOME,
    <span class="hljs-attr">payload</span>: value
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SUBSOME = <span class="hljs-string">'SUBSOME'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> subSome = <span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> ({
    <span class="hljs-attr">type</span>: SUBSOME,
    <span class="hljs-attr">payload</span>: value
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RESET = <span class="hljs-string">'RESET'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> reset = <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">type</span>: RESET })
</code></pre>
<ul>
<li>And last comes our component. Here we have 3 things to notice:</li>
</ul>
<ol>
<li><p>First we have a <strong>provider</strong> component that receives <strong>store</strong> as props. This is what grants access to our store from all the components wrapped in it.</p>
</li>
<li><p>Then we have a hook called <strong>useDispatch()</strong> (that we'll use to dispatch actions) and another called <strong>useSelector()</strong> (that we'll use to read the state from the store).</p>
</li>
<li><p>Last, notice we're <strong>dispatching the functions</strong> we declared on the actions file, and passing a value as an input when it corresponds. This value is what the actions takes as payload and what the reducer is going to use to modify the state. ;)</p>
</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</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> { addOne, subOne, addSome, subSome, reset } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/actions/count.actions'</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> dispatch = useDispatch()
  <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">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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(addOne())}&gt;Add 1<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(subOne())}&gt;Decrease 1<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(addSome(10))}&gt;Add 10<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(subSome(10))}&gt;Decrease 10<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(reset())}&gt;Reset count<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> App
</code></pre>
<p>Redux is a nice tool that solves two problems at the same time (prop drilling and complex state changes). Still, it does generate a lot of boilerplate and makes state management a topic that's harder to get your head around, specially when dealing with different files and entities like actions, reducers, a store...</p>
<p>An important thing to mention here is that these tools or ways to manage state aren't mutually exclusive, they can and probably should be used at the same time, each to solve the specific problem they're good at.</p>
<p>In the case of Redux, that problem is handling <strong>global state</strong> (meaning state that affects your whole application or a very big part of it). It wouldn't make sense to use Redux to handle a counter like our example or the opening and closing of a modal.</p>
<p>A good golden rule is <strong>useState for component state, Redux for application state</strong>.</p>
<h1 id="heading-alternatives-to-redux">Alternatives to Redux</h1>
<p>If this topic isn't yet complicated enough for you, in the last few years a lot of new libraries have come up as alternatives to Redux, each with its own approach to state management.</p>
<p>Just for the sake of getting a good overview, let's quickly get to know them.</p>
<h2 id="heading-redux-toolkit">Redux toolkit</h2>
<p><a target="_blank" href="https://redux-toolkit.js.org/">Redux toolkit</a> is a library built on top of Redux, which aims to take away some of the complexity and boilerplate that Redux generates.</p>
<p>Redux toolkit is built upon two things:</p>
<ul>
<li><p>A <strong>store</strong>, which works exactly the same as a plain Redux store</p>
</li>
<li><p>And <strong>slices</strong> which condense plain Redux actions and reducers into a single thing</p>
</li>
</ul>
<p>Implementing Redux Toolkit, our example app would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</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> { addOne, subOne, addSome, subSome, reset } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/slices/count.slice'</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> dispatch = useDispatch()
  <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">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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(addOne())}&gt;Add 1<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(subOne())}&gt;Decrease 1<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(addSome(10))}&gt;Add 10<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(subSome(10))}&gt;Decrease 10<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(reset())}&gt;Reset count<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> App
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// index.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> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</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/index'</span>

ReactDOM.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>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
)
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Index.jsx (STORE)</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> counterReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./slices/count.slice'</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
  },
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// count.slice.jsx</span>
<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">addOne</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">subOne</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">addSome</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {state.count += action.payload},
    <span class="hljs-attr">subSome</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {state.count -= action.payload},
    <span class="hljs-attr">reset</span>: <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> {state.count = <span class="hljs-number">0</span>}
  },
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addOne, subOne, addSome, subSome, reset } = counterSlice.actions

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> counterSlice.reducer
</code></pre>
<ul>
<li><p>First we need to <strong>install it</strong> by running <code>npm install @reduxjs/toolkit react-redux</code></p>
</li>
<li><p>On our <strong>store</strong> we import the <code>configureStore</code> function from Redux toolkit, and create the store by calling this function and passing it an object with a reducer, which itself is an object that contains a slice.</p>
</li>
</ul>
<pre><code class="lang-js"><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>
<ul>
<li>A <strong>slice</strong>, as I mentioned, is a way to condense actions and reducers into the same thing. We import the <code>createSlice</code> function from Redux toolkit, then declare the initial state and initialize the slice.</li>
</ul>
<p>This one will receive as parameters the name of the slice, the initial state, and the functions we'll dispatch from our components in order to modify the state.</p>
<p>Notice there are no actions here. The UI will call the reducer functions directly. That's the complexity Redux toolkit "takes away".</p>
<pre><code class="lang-js"><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">addOne</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">subOne</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">addSome</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {state.count += action.payload},
    <span class="hljs-attr">subSome</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {state.count -= action.payload},
    <span class="hljs-attr">reset</span>: <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> {state.count = <span class="hljs-number">0</span>}
  },
})
</code></pre>
<ul>
<li>On index.js we wrap our app around a provider component so that we can access state from anywhere.</li>
</ul>
<pre><code class="lang-js">    &lt;Provider store={store}&gt;
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>
    &lt;/Provider&gt;
</code></pre>
<ul>
<li>And lastly, from our component we read the state and dispatch modification functions using hooks just like with plain Redux.</li>
</ul>
<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">const</span> dispatch = useDispatch()
  <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">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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch(addOne())}&gt;Add 1<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(subOne())}&gt;Decrease 1<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(addSome(10))}&gt;Add 10<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(subSome(10))}&gt;Decrease 10<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(reset())}&gt;Reset count<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>Redux toolkit aims to be a simpler way to deal with Redux, but in my opinion it's still almost the same boilerplate and not much of a difference with plain Redux.</p>
<h3 id="heading-a-mention-for-redux-thunk-and-redux-saga">A mention for Redux Thunk and Redux Saga</h3>
<p><a target="_blank" href="https://github.com/reduxjs/redux-thunk">Redux thunk</a> and <a target="_blank" href="https://redux-saga.js.org/">Redux Saga</a> are other two popular middleware libraries that are used <strong>together</strong> with Redux.</p>
<p>Specifically, both Thunk and Saga are meant to be used when dealing with side effects or assynchronous tasks.</p>
<h2 id="heading-recoil">Recoil</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/2CYCmD92D.png" alt="2CYCmD92D" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://recoiljs.org/">Recoil</a> is an open source state management library specifically for React built by Facebook (or Meta, whatever...). According to their website, Recoil is built to be "minimal and reactish", in the sense that it looks and feels like plain React code.</p>
<p>Recoil is based upon the idea of <strong>atoms</strong>. Quoting their docs,</p>
<blockquote>
<p>"An atom represents a piece of state. Atoms can be read from and written to from any component. Components that read the value of an atom are implicitly subscribed to that atom, so any atom updates will result in a re-render of all components subscribed to that atom".</p>
</blockquote>
<p>Using Recoil, our example app would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> countState <span class="hljs-keyword">from</span> <span class="hljs-string">'./recoil/counter.atom'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</span>

<span class="hljs-keyword">import</span> { useRecoilState } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</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, setCount] = useRecoilState(countState)

  <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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count+1)}&gt;Add 1<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;Decrease 1<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+10)}&gt;Add 10<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-10)}&gt;Decrease 10<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(0)}&gt;Reset count<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> App
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// index.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> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>
<span class="hljs-keyword">import</span> { RecoilRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</span>

ReactDOM.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">RecoilRoot</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">RecoilRoot</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
)
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// counter.atom.jsx</span>
<span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">'recoil'</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>
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> countState
</code></pre>
<p>As you can probably immediately see, this is a lot less boilerplate than Redux. =D</p>
<ul>
<li><p>First we install it by running <code>npm install recoil</code></p>
</li>
<li><p>Components that use recoil state need <code>RecoilRoot</code> to appear somewhere in the parent tree. So we wrap our app with it.</p>
</li>
</ul>
<pre><code class="lang-js">  &lt;React.StrictMode&gt;
    <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">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RecoilRoot</span>&gt;</span></span>
  &lt;/React.StrictMode&gt;
</code></pre>
<ul>
<li>Then we declare our <strong>atom</strong>, which is just an object containing a key and a default value:</li>
</ul>
<pre><code class="lang-plaintext">const countState = atom({
  key: 'countState', // unique ID (with respect to other atoms/selectors)
  default: 0 // default value (aka initial value)
})
</code></pre>
<ul>
<li>Lastly, in our component we import the hook <code>useRecoilState</code> and declare our state with it, passing it the unique key we just declared in our atom.</li>
</ul>
<pre><code class="lang-plaintext">const [count, setCount] = useRecoilState(countState)
</code></pre>
<p>As you can see, this looks really similar to a regular useState hook. <em>Reactish</em>... =P</p>
<p>And from our UI, we just call the <code>setCount</code> function to update our state.</p>
<pre><code class="lang-js">&lt;button onClick={<span class="hljs-function">() =&gt;</span> setCount(count+<span class="hljs-number">1</span>)}&gt;Add <span class="hljs-number">1</span>&lt;/button&gt;
</code></pre>
<p>Minimal, and very easy to use. Recoil is still kind of experimental and not that widely used, but you can see how devs around the world would turn to this tool.</p>
<h2 id="heading-jotai">Jotai</h2>
<p><a target="_blank" href="https://jotai.org/">Jotai</a> is an open source state management library built for React that is inspired by Recoil. It differs from Recoil in looking for an even more minimalistic API – it doesn't use string keys and it's TypeScript-oriented.</p>
<p>Same as with Recoil, Jotai uses atoms. An <strong>atom</strong> represents a piece of state. All you need is to specify an initial value, which can be primitive values like strings and numbers, objects and arrays. Then in your components you consume that atom, and on every atom change that component will re-render.</p>
<p>Using Jotai, our example app looks like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</span>

<span class="hljs-keyword">import</span> { useAtom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</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, setCount] = useAtom(countAtom)

  <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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count+1)}&gt;Add 1<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;Decrease 1<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+10)}&gt;Add 10<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-10)}&gt;Decrease 10<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(0)}&gt;Reset count<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> App
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// counter.atom.jsx</span>
<span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</span>

<span class="hljs-keyword">const</span> countAtom = atom(<span class="hljs-number">0</span>)

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> countAtom
</code></pre>
<p>As you can see, it's even more minimal than Recoil.</p>
<ul>
<li><p>We install it by running <code>npm install jotai</code></p>
</li>
<li><p>Then we declare an atom with a default value:</p>
</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> countAtom = atom(<span class="hljs-number">0</span>)
</code></pre>
<ul>
<li>And consume it with our component using <code>useAtom</code>:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [count, setCount] = useAtom(countAtom)
</code></pre>
<p>Really nice and simple!</p>
<h2 id="heading-zustand">Zustand</h2>
<p><a target="_blank" href="https://github.com/pmndrs/zustand">Zustand</a> is another open source state management library built for React. It's inspired by Flux, a library widely used before Redux came around, and it aims to be</p>
<blockquote>
<p>"a small, fast non-opinionated and scalable barebones state-management solution with a comfy API based on hooks and almost no boilerplate".</p>
</blockquote>
<p>Zustand uses a store in a similar way that Redux does, but with the difference that in Zustand the store is now a hook, and it takes far less boilerplate.</p>
<p>Using Zustand, our example app would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.scss'</span>
<span class="hljs-keyword">import</span> useStore <span class="hljs-keyword">from</span> <span class="hljs-string">'./store'</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 = useStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.count)
  <span class="hljs-keyword">const</span> { addOne, subOne, add10, sub10, reset } = useStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state)

  <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">p</span>&gt;</span>Count is: {count}<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">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addOne()}&gt;Add 1<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> subOne()}&gt;Decrease 1<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> add10()}&gt;Add 10<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> sub10()}&gt;Decrease 10<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> reset()}&gt;Reset count<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> App
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Index.jsx (STORE)</span>
<span class="hljs-keyword">import</span> create <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand'</span>

<span class="hljs-keyword">const</span> useStore = create(<span class="hljs-function"><span class="hljs-params">set</span> =&gt;</span> ({
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">addOne</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count += <span class="hljs-number">1</span>})),
  <span class="hljs-attr">subOne</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count -= <span class="hljs-number">1</span>})),
  <span class="hljs-attr">add10</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count += <span class="hljs-number">10</span>})),
  <span class="hljs-attr">sub10</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count -= <span class="hljs-number">10</span>})),
  <span class="hljs-attr">reset</span>: <span class="hljs-function">() =&gt;</span> set({<span class="hljs-attr">count</span>: <span class="hljs-number">0</span>})
}))

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useStore
</code></pre>
<ul>
<li><p>We install it by running <code>npm install zustand</code></p>
</li>
<li><p>We create a store with the <code>create</code> function we imported from Zustand. Inside we set the default state and functions we will use to modify the state.</p>
</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> useStore = create(<span class="hljs-function"><span class="hljs-params">set</span> =&gt;</span> ({
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">addOne</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count += <span class="hljs-number">1</span>})),
  <span class="hljs-attr">subOne</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count -= <span class="hljs-number">1</span>})),
  <span class="hljs-attr">add10</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count += <span class="hljs-number">10</span>})),
  <span class="hljs-attr">sub10</span>: <span class="hljs-function">() =&gt;</span> set(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({<span class="hljs-attr">count</span>: state.count -= <span class="hljs-number">10</span>})),
  <span class="hljs-attr">reset</span>: <span class="hljs-function">() =&gt;</span> set({<span class="hljs-attr">count</span>: <span class="hljs-number">0</span>})
}))
</code></pre>
<ul>
<li>Then in our component we import the store we just created, and read the state and modifying functions from it in the following way:</li>
</ul>
<pre><code class="lang-js">  <span class="hljs-keyword">const</span> count = useStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.count)
  <span class="hljs-keyword">const</span> { addOne, subOne, add10, sub10, reset } = useStore(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state)
</code></pre>
<p>Our UI can call the modifying functions just like this:</p>
<pre><code class="lang-js">&lt;button onClick={<span class="hljs-function">() =&gt;</span> addOne()}&gt;Add <span class="hljs-number">1</span>&lt;/button&gt;
</code></pre>
<p>You can see how Zustand comes from the same concepts of Redux, with a much cleaner and simpler approach.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>State management is one of the most complicated topics when it comes to front end development. And you can see how many people have tried to make it work in a predictable and scalable way, but also in ways that are clean and easy to use.</p>
<p>Specially in the last years, a lot of good tools have come up offering nice ways to deal with state management.</p>
<p>As developers, though, we have to keep in mind that Redux and other libraries where created to solve specific state management problems, specially in really big, complex, and heavily-used apps.</p>
<p>I think that If you don't run into these problems, there's really no need to add extra boilerplate and complicate your code. Even with modern libraries that add almost no boilerplate.</p>
<p>React itself is a very strong and solid library, and tools like useState, useReducer, and useContext are quite enough to solve most problems. So I would stick to the basics unless for some reason the basics are no longer enough.</p>
<p>When in need of a more specific and robust state management library, I think the choice is a matter of deciding between reliability and simplicity.</p>
<p>Redux is the most mature and used library, and that comes with lots of documentation, online communities, and previous bugs found and solved with each new release.</p>
<p>The bad thing about it is, as developers, it presents us with some new concepts we have to learn and think about. We also need to add quite a bit of code just to make it work, and it can add more complexity than the problems that it helps to solve.</p>
<p>On the contrary, modern libraries like we've seen are much simpler and straight to the point, but aren't as widely used and tested, and are still kind of experimental.</p>
<p>But for what we can see at the moment, it seems just a matter of time until one or some of them take the lead and become the more widely used tool.</p>
<p>That's it! I hoped you enjoyed the article and learned something new. If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">linkedin</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">twitter</a>. Cheers and see you in the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Redux Tutorial for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Redux is a popular open-source JavaScript library for managing and centralizing application state. It is commonly used with React. We just published a complete course on the freeCodeCamp.org YouTube channel that will teach you how to use Redux. Nikhi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/redux-tutorial-for-beginners/</link>
                <guid isPermaLink="false">66b206544818b8d659cc815b</guid>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 03 Mar 2022 18:38:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/redux.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Redux is a popular open-source JavaScript library for managing and centralizing application state. It is commonly used with React.</p>
<p>We just published a complete course on the freeCodeCamp.org YouTube channel that will teach you how to use Redux.</p>
<p>Nikhil Thadani developed this course. Nikhil has created many technical courses on his YouTube channel.</p>
<p>In this course you will learn how to use Redux with ReduxToolkit Library to create an application involving HTTP requests.</p>
<p>Here are the topics covered in this course:</p>
<ul>
<li>Basic Terminologies</li>
<li>Counter App with react-redux</li>
<li>Using Redux Toolkit</li>
<li>Shopping Cart Project - Introduction</li>
<li>Shopping Cart Project - Auth Slice State</li>
<li>Shopping Cart Project - Cart Slice State</li>
<li>Incrementing and Decrementing Items From Cart</li>
<li>Adding Logout State</li>
<li>Using Firebase with Redux</li>
<li>Sending asynchronous HTTP Requests with Redux</li>
<li>Adding Notifications with Material UI</li>
<li>Adding Notification slice state</li>
<li>Using Redux Thunk Pattern</li>
<li>Creating Thunk Pattern with redux</li>
<li>Sending GET HTTP request with Redux</li>
</ul>
<p>Watch the full course below or <a target="_blank" href="https://youtu.be/zrs7u6bdbUw">on the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/zrs7u6bdbUw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Snake Game with React, Redux, and Redux Saga ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I am going to walk you through creating a snake game using a React application. It is a simple 2d game built using TypeScript, and we won't need to use any third-party graphics libraries to build it.  This is what we'll make in this ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-snake-game-with-react-redux-and-redux-sagas/</link>
                <guid isPermaLink="false">66bb553d343f42327e719662</guid>
                
                    <category>
                        <![CDATA[ Games ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Keyur Paralkar ]]>
                </dc:creator>
                <pubDate>Wed, 09 Feb 2022 18:03:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/pexels-pixabay-80474.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I am going to walk you through creating a snake game using a React application. It is a simple 2d game built using TypeScript, and we won't need to use any third-party graphics libraries to build it. </p>
<p>This is what we'll make in this tutorial:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/ezgif.com-gif-maker--2-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Snake is a fun game which you might have played on older feature phones like on Nokia 3310 models. </p>
<p>The concept behind it is simple: the snake roams around inside a box, and once it captures the fruit/object your points increase and the snake grows. If the snake hits the boundaries of the box or collides with itself then the game is over. </p>
<p>This article will provide you with all the necessary skills/steps to create your own Snake game from scratch. We'll first look at the code structures and their logic. Then I'll explain how they work when all of them are connected.</p>
<p>Without further ado, let’s get started.</p>
<h2 id="heading-table-of-contents">Table of contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-snake-game-what-are-we-going-to-use-in-it">What is a snake game? What are we going to use in it?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-redux-why-are-we-using-it">What is redux? Why are we using this?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-redux-saga-why-are-we-using-it">What is redux-saga? Why are we using this?</a></li>
<li><a class="post-section-overview" href="#heading-use-case-description">Use case description</a></li>
<li><a class="post-section-overview" href="#heading-the-application-and-data-layer-set-up">The application and data layer set up</a></li>
<li><a class="post-section-overview" href="#heading-understanding-ui-layer">Understanding UI Layer</a></li>
<li><a class="post-section-overview" href="#heading-canvas-board">Canvas Board</a></li>
<li><a class="post-section-overview" href="#heading-drawing-the-objects">Drawing the objects</a></li>
<li><a class="post-section-overview" href="#heading-moving-the-snake-across-the-board">Moving the snake across the board</a></li>
<li><a class="post-section-overview" href="#heading-drawing-the-fruit-at-a-random-position">Drawing the fruit at a random position</a></li>
<li><a class="post-section-overview" href="#heading-score-calculator">Score calculator</a></li>
<li><a class="post-section-overview" href="#heading-instruction-component">Instruction component</a></li>
<li><a class="post-section-overview" href="#heading-final-game">Final Game</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start reading this article, you should have a basic understanding of the following topics:</p>
<ul>
<li>Class Diagrams: We are going to use them to showcase our example. Here are a couple of resources you can use to learn more about them:<ul>
<li><a target="_blank" href="https://drawio-app.com/uml-class-diagrams-in-draw-io/">Class diagrams</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/uml-diagrams-full-course/">UML Diagram course</a></li>
</ul>
</li>
<li><a target="_blank" href="https://www.notion.so/JS-Classes-a-boon-to-the-society-6360d1a702fe49da9b7ba98b0e03fe37">Context Diagram and Container Diagrams</a></li>
<li><a target="_blank" href="https://reactjs.org/">React</a></li>
<li>Generators:<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator">Generators</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*">Function generators</a></li>
</ul>
</li>
</ul>
<h2 id="heading-what-is-a-snake-game-what-are-we-going-to-use-in-it">What is a snake game? What are we going to use in it?</h2>
<p>A snake game is an arcade game that involves a snake moving inside a box. Your score increases based on how many objects/fruit the snake eats. This will also increase the size of the snake. If it collides with itself or to the boundary of the box then the game is over. </p>
<p>You can read more about the history or the origins of the game in the Wiki <a target="_blank" href="https://en.wikipedia.org/wiki/Snake_(video_game_genre)">link</a>.</p>
<p>We are going to use the following tools to build our game:</p>
<ul>
<li>Redux: To create and manage the global state for the application.</li>
<li>Redux-saga: A redux middleware we'll use to manage async tasks.</li>
<li>Canvas HTML tag: We'll use this to draw an object like a snake and the fruit.</li>
<li>React: UI library.</li>
<li>Chakra-UI: Component library.</li>
</ul>
<h2 id="heading-what-is-redux-why-are-we-using-it">What is redux? Why are we using it?</h2>
<p>Redux is a state container that helps you create and manage global state for your application. Redux consists of some basic parts like:</p>
<ol>
<li>Global State</li>
<li>Redux store</li>
<li>Actions and action creators</li>
<li>Reducers</li>
</ol>
<p>You can learn all about the above topics and how Redux works internally from the Redux doc’s getting started <a target="_blank" href="https://redux.js.org/introduction/getting-started">section</a>.</p>
<p>We are using the state management library Redux because it will help us manage our global state in a simpler way. It will allow us to avoid prop drilling. It will also allow us to perform complex async actions via middleware. </p>
<p>You can learn more about middleware <a target="_blank" href="https://redux.js.org/understanding/history-and-design/middleware">here</a>.</p>
<h2 id="heading-what-is-redux-saga-why-are-we-using-it">What is redux-saga? Why are we using it?</h2>
<p>Redux-saga is a middleware that helps us tap in between the dispatched action and the reducer of the redux store. This allows us to perform certain side-effects between the dispatched action and the reducer such as data fetching, listening to particular actions or setting up subscriptions, spawning actions, and more.</p>
<p>Redux saga uses generators and generator functions. A typical saga would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">performAction</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">yield</span> put({
        <span class="hljs-attr">type</span>: COPY_DATA,
        <span class="hljs-attr">payload</span>: <span class="hljs-string">"Hello"</span>
    });
}
</code></pre>
<p><code>performAction</code> is a generator function. This generator function will execute the <code>put</code> function. It creates an object and returns it to the saga, telling what type of action needs to be executed with what payload. Then the <code>put</code> call returns an object descriptor saying which saga can take it up later and execute the particular action.</p>
<p><strong>NOTE:</strong> You can read more about generators and generator functions by referring to the prerequisite section.</p>
<p>Now the question arises <em>Why are we using redux-saga middleware?</em> The answer is simple:</p>
<ol>
<li>It provides a better way to write unit test cases, which will help us test the generator functions in a simpler way.</li>
<li>It can help you perform a lot of side effects and provide better control over the changes. One example is whenever you want to watch if a particular action X is executed then perform the action Y. Functions like <code>takeEvery</code>, <code>all</code>, and so on make it simple to perform these operations. We will discuss more of this in a later section.</li>
</ol>
<p>If you are not familiar with redux-saga, then I highly recommend going through the documentation <a target="_blank" href="https://redux-saga.js.org/docs/introduction/GettingStarted/">here</a>.</p>
<h2 id="heading-use-case-description">Use case description</h2>
<p><strong>NOTE:</strong> Context, Container, and Class diagrams drawn in this blog post don't accurately follow the exact conventions of these diagrams. I've approximated them here so you can understand the basic concepts.</p>
<p>Before we start, I would suggest reading up on c4models, container diagrams, and context diagrams. You can find resources about them in the prerequisites section.</p>
<p>In this article we are going to consider the following use case: <em>Create a snake game</em>.</p>
<p>The use case is pretty self-explanatory, and we have discussed what the snake game entails above. Below is the context diagram for our use case:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/contextDiagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>Snake game context diagram</em></p>
<p>Our context diagram is pretty straightforward. The player interacts with the UI. Let's dive deeper into the container game board UI and explore what other systems are present inside it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/Untitled--2-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Container diagram for the snake game</em></p>
<p>As you can see from the above diagram, our Game Board UI is divided into two Layers:</p>
<ol>
<li>UI Layer</li>
<li>Data Layer</li>
</ol>
<p>The UI Layer consists of the following components:</p>
<ol>
<li><strong>Score Calculator:</strong> This is a component that will display the score whenever the snake eats the fruit.</li>
<li><strong>Canvas Board:</strong> This is a component that handles the major UI part of our game. Its basic functionality is to draw the snake on the canvas and clear the canvas. It also handles the following responsibilities:<ol>
<li>It detects if the snake has collided with itself or with the boundary walls (Collision detection).</li>
<li>Helps in moving the snake along the board with keyboard events.</li>
<li>Resets the game when the game is over.</li>
</ol>
</li>
<li><strong>Instructions:</strong> It provides the instructions for playing the game, along with the reset button.</li>
<li><strong>Utilities:</strong> These are the utility functions that we'll use throughout the application wherever needed.</li>
</ol>
<p>Let's now talk about the Data Layer. It consists of the following components:</p>
<ol>
<li><strong>Redux-saga:</strong> Set of generator functions that will perform certain actions.</li>
<li><strong>Actions and Action Creators:</strong> These are the set of constants and functions which will help in dispatching appropriate actions.</li>
<li><strong>Reducers:</strong> This will help us respond to the various actions dispatched by action creators and the sagas.</li>
</ol>
<p>We will deep dive into all of these components and see how they work collectively in the later sections. First, let's initialize our project and set up our Data layer – that is, the Redux store.</p>
<h2 id="heading-the-application-and-data-layer-set-up">The application and data layer set up</h2>
<p>Before we start understanding our game components, let's first set up our React application and the data layer. </p>
<p>The game is built with React. I highly recommend using the <a target="_blank" href="https://create-react-app.dev/">create-react-app</a> template to install all the necessary things to start your React application. </p>
<p>To create a CRA (create-react-app) project, first we need to install it. Type the below command into your terminal:</p>
<pre><code class="lang-shell">npm install -g create-react-app
</code></pre>
<p><strong>Note:</strong> Before running this command make sure you have installed Node.js in your system. Follow this <a target="_blank" href="https://nodejs.org/en/download/package-manager/">link</a> to install it.</p>
<p>Next, we will start by creating our project. Let's call it snake-game. Type the below command into your terminal to create the project:</p>
<pre><code class="lang-shell">npx create-react-app snake-game
</code></pre>
<p>This may take few minutes to complete. Once this is completed, traverse to your newly created project using the below command:</p>
<pre><code class="lang-shell">cd snake-game
</code></pre>
<p>Once inside the project, type the below command to start the project:</p>
<pre><code class="lang-shell">npm run start
</code></pre>
<p>This command will open a new tab in your browser with the React logo spinning on the page like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-16.png" alt="Image" width="600" height="400" loading="lazy">
<em>create-react-app initial page</em></p>
<p>Now our initial project setup is complete. Let's configure our data layer (the Redux store). Our data layer requires that we install the following packages:</p>
<ul>
<li>Redux</li>
<li>Redux-saga</li>
</ul>
<p>First, let's start off by installing these packages. Before we start, make sure you are in the project directory. Type the below command in the terminal:</p>
<pre><code class="lang-shell">npm install redux react-redux redux-saga
</code></pre>
<p>Once these packages are installed then we will first configure our Redux store. To start off, let's first create a folder named <code>store</code>:</p>
<pre><code class="lang-shell">mkdir store
</code></pre>
<p>This <code>store</code> folder will consist of all the files related to Redux. We will organize our store folder in the following manner:</p>
<pre><code class="lang-shell">store/
├── actions
│   └── index.ts
├── reducers
│   └── index.ts
└── sagas
    └── index.ts
├── index.ts
</code></pre>
<p>Let's discuss what each of the files does:</p>
<ul>
<li><code>action/index.tsx</code>: This file consists of constants that represents actions that our application can perform and dispatch to the Redux store. An example of such an action constant looks like this:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MOVE_RIGHT = <span class="hljs-string">"MOVE_RIGHT"</span>
</code></pre>
<p>We will use the same action constant to create a function which will return an object with the following properties:</p>
<ul>
<li><code>type</code>: Action type, that is action constant</li>
<li><code>payload</code>: additional data that acts as a payload.</li>
</ul>
<p>These functions which return an object with the <code>type</code> property are called action creators. We use these functions to dispatch actions to our Redux store. </p>
<p>The <code>payload</code> attribute signifies that along with the action we can also pass additional data which can be used to store or update the value inside the global state.</p>
<p><strong>NOTE</strong>: It is mandatory to have <code>type</code> property returned from the action creator. The <code>payload</code> property is optional. Also, the name of the <code>payload</code> property can be anything.</p>
<p>Let's see an example of an action creator:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Without payload</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> moveRight = <span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">type</span>: MOVE_RIGHT
});

<span class="hljs-comment">//With payload</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> moveRight = <span class="hljs-function">(<span class="hljs-params">data: string</span>) =&gt;</span> ({
    <span class="hljs-attr">type</span>: MOVE_RIGHT,
    <span class="hljs-attr">payload</span>: data
});
</code></pre>
<p>Now that we know what actions and action creators are, we can move on to configuring our next artifact which is a reducer.</p>
<p>Reducers are functions that return a new global state every time an action is dispatched. They take in the current global state and return the new state based on the action that is dispatched/called.  This new state is calculated based on the previous state. </p>
<p>We should be careful here that we do not perform any side-effects inside this function. We should not alter the global state – rather we should return the updated state as a new object itself. Therefore, the reducer function should be a pure function.</p>
<p>Now enough talking about reducers. Let's have a look at our sample reducers:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> GlobalState = {
    <span class="hljs-attr">data</span>: <span class="hljs-string">""</span>
};

<span class="hljs-keyword">const</span> gameReducer = <span class="hljs-function">(<span class="hljs-params">state = GlobalState, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"MOVE_RIGHT"</span>:
            <span class="hljs-comment">/**
             * Perform a certain set of operations
             */</span>
            <span class="hljs-keyword">return</span> {
                ...state, <span class="hljs-attr">data</span>: action.payload
            };

        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> state;
    }
}
</code></pre>
<p>In this example, we have created a reducer function which is called a <code>gameReducer</code>. It takes in the state (default parameter as a global state) and an action. Whenever we have <code>action.type</code> that matches the switch case, then it performs a particular action, like returning a new state based on the action. </p>
<p>The <code>sagas/index.ts</code> file will consist of all the sagas that we will use in our application. We do have some basic understanding of the sagas which we briefly explained in the above sections. We will dive deeper into this section when we actually start our implementation of the snake game. </p>
<p>Now we have a basic understanding of the artifacts involved in making our Redux store. Let's go ahead and create <code>store/index.ts</code> like below:</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> gameReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./reducers"</span>;
<span class="hljs-keyword">import</span> watcherSagas <span class="hljs-keyword">from</span> <span class="hljs-string">"./sagas"</span>;
<span class="hljs-keyword">const</span> sagaMiddleware = createSagaMiddleware();

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

sagaMiddleware.run(watcherSagas);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</code></pre>
<p>We will first import our reducer and the saga. Next we will use the <code>createSagaMiddleware()</code> function to create a saga middleware. </p>
<p>Next, we will connect it to our store by passing it as an argument to the <code>applyMiddleware</code> function inside <code>createStore</code> which you use to create a store. We will also pass <code>gameReducer</code> to this function so that a reducer is mapped to our store.</p>
<p>Finally, we will run our sagaMiddleware using this code:</p>
<pre><code class="lang-javascript">sagaMiddleware.run(watcherSagas);
</code></pre>
<p>Our final step is to inject this <code>store</code> at the top level of our React app using the <code>Provider</code> component provided by <code>react-redux</code>. You can do this as follows:</p>
<pre><code class="lang-jsx"><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>;

<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">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
    //   Child components...
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>I have also installed chakra-UI as a UI component library for our project. To install chakra-UI, type the below command:</p>
<pre><code class="lang-shell">npm install @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^5
</code></pre>
<p>We also need to setup the <code>ChakraProvider</code> that will go in our <code>App.tsx</code> file. Our updated <code>App.tsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { ChakraProvider, Container, Heading } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/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> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./store"</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">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">ChakraProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Container</span> <span class="hljs-attr">maxW</span>=<span class="hljs-string">"container.lg"</span> <span class="hljs-attr">centerContent</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h1"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"xl"</span>&gt;</span>SNAKE GAME<span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
    //Children components
        <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-understanding-ui-layer">Understanding UI layer</h2>
<p>Let's first understand the dynamics of our Snake game from the UI perspective. Before we get started, our final Snake game will look like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/snake-game.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The UI Layer consists of 3 layers: <strong>Score Calculator</strong>, <strong>Canvas Board</strong>, and <strong>Instructions</strong>. The below diagram showcases these sections:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/Untitled--3-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's dive deeper into each of these sections to understand how our Snake game works.</p>
<h2 id="heading-canvas-board">Canvas Board</h2>
<p>We'll start off by understanding the Canvas Board:</p>
<ul>
<li>Our canvas board is going to be of dimensions <code>height: 600, width: 1000</code></li>
<li>This entire board is divided into blocks of <code>20x20</code> size. That is, every object that is drawn on this board has <code>height 20</code> and <code>width 20</code>.</li>
<li>We are using the <code>&lt;canvas&gt;</code> HTML element to draw the shapes in the canvas board component.</li>
</ul>
<p>In our project, we are writing the canvas board component inside the file <code>components/CanvasBoard.tsx</code>. Now that our basic understanding is clear about the CanvasBoard component, let's start building this component.</p>
<p>Create a simple component that returns a canvas element as below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> interface ICanvasBoard {
  <span class="hljs-attr">height</span>: number;
  width: number;
}

<span class="hljs-keyword">const</span> CanvasBoard = <span class="hljs-function">(<span class="hljs-params">{ height, width }: ICanvasBoard</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">border:</span> "<span class="hljs-attr">3px</span> <span class="hljs-attr">solid</span> <span class="hljs-attr">black</span>",
      }}
      <span class="hljs-attr">height</span>=<span class="hljs-string">{height}</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">{width}</span>
    /&gt;</span></span>
  );
};
</code></pre>
<p>Call this component in our <code>App.tsx</code> file with width and height of 1000 and 600 as a prop like below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { ChakraProvider, Container, Heading } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/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> CanvasBoard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/CanvasBoard"</span>;
<span class="hljs-keyword">import</span> ScoreCard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/ScoreCard"</span>;
<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./store"</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">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">ChakraProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Container</span> <span class="hljs-attr">maxW</span>=<span class="hljs-string">"container.lg"</span> <span class="hljs-attr">centerContent</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h1"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"xl"</span>&gt;</span>SNAKE GAME<span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">CanvasBoard</span> <span class="hljs-attr">height</span>=<span class="hljs-string">{600}</span> <span class="hljs-attr">width</span>=<span class="hljs-string">{1000}</span> /&gt;</span> //Canvasboard component added 
        <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>This will create a simple box of height=600 and width=1000 with a black border like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/snakeCanvas1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A blank canvas element with width=1000 and height=600</em></p>
<p>Now let's draw a snake at the center of this canvas. But before we can start drawing, we need to get the context of this <code>canvas</code> element. </p>
<p>The context of a canvas element provides you with all the information you need related to the canvas element. It gives you the dimensions of the canvas and also helps you draw on the canvas. </p>
<p>To get the context of our canvas element we need to call the <code>getCanvas('2d')</code> function which returns the 2d context of the canvas. The return type of this function is <code>CanvasRenderingContext2D</code> interface. </p>
<p>To do this in pure JS we would do something like below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'canvas'</span>);
<span class="hljs-keyword">const</span> canvasCtx = canvas.getContext(<span class="hljs-string">'2d'</span>);
</code></pre>
<p>But to do so in React we need to create a <code>ref</code> and pass it to the canvas element so that we can address it later in different hooks. To do so in our application, create one <code>ref</code> using the <code>useRef</code> hook:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> canvasRef = useRef&lt;HTMLCanvasElement | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
</code></pre>
<p>Pass the ref into our <code>canvas</code> element:</p>
<pre><code class="lang-jsx">&lt;canvas
  ref={canvasRef}
  style={{
    <span class="hljs-attr">border</span>: <span class="hljs-string">"3px solid black"</span>,
  }}
  height={height}
  width={width}
/&gt;;
</code></pre>
<p>Once the <code>canvasRef</code> is passed into the <code>canvas</code> element, we can use it inside a <code>useEffect</code> hook and store the context in a state variable. </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> interface ICanvasBoard {
  <span class="hljs-attr">height</span>: number;
  width: number;
}

<span class="hljs-keyword">const</span> CanvasBoard = <span class="hljs-function">(<span class="hljs-params">{ height, width }: ICanvasBoard</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> canvasRef = (useRef &lt; HTMLCanvasElement) | (<span class="hljs-literal">null</span> &gt; <span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [context, setContext] =
    (useState &lt; CanvasRenderingContext2D) | (<span class="hljs-literal">null</span> &gt; <span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//Draw on canvas each time</span>
    setContext(canvasRef.current &amp;&amp; canvasRef.current.getContext(<span class="hljs-string">"2d"</span>)); <span class="hljs-comment">//store in state variable</span>
  }, [context]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{canvasRef}</span>    
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">border:</span> "<span class="hljs-attr">3px</span> <span class="hljs-attr">solid</span> <span class="hljs-attr">black</span>",
      }}
      <span class="hljs-attr">height</span>=<span class="hljs-string">{height}</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">{width}</span>
    /&gt;</span></span>
  );
};
</code></pre>
<h2 id="heading-drawing-the-objects">Drawing the objects</h2>
<p>After getting the context we need to do the following tasks each time a component updates:</p>
<ol>
<li>Clear the canvas</li>
<li>Draw the snake with the current position</li>
<li>Draw a fruit at a random position inside the box</li>
</ol>
<p>We are going to clear the canvas multiple times, so we will make this a utility function. So for that, let's create a folder called <code>utilities</code>:</p>
<pre><code class="lang-shell">mkdir utilities
cd utilities
touch index.tsx
</code></pre>
<p>The above command will also create an <code>index.tsx</code> file inside the utilities folder. Add the below code in the <code>utilities/index.tsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> clearBoard = <span class="hljs-function">(<span class="hljs-params">context: CanvasRenderingContext2D | <span class="hljs-literal">null</span></span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (context) {
    context.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1000</span>, <span class="hljs-number">600</span>);
  }
};
</code></pre>
<p>The <code>clearBoard</code> function is pretty straightforward. It does the following actions:</p>
<ol>
<li>It accepts the 2d canvas context objects as an argument.</li>
<li>It checks that the context is not null or undefined.</li>
<li>The <code>clearRect</code> function will clear all the pixels or objects present inside the rectangle. This function will take width and height as an argument for the rectangle to be cleared.</li>
</ol>
<p>We will use this <code>clearBoard</code> function inside our <code>CanvasBoard</code> useEffect to clear the canvas every time the component is updated. For differentiating between different <code>useEffects</code>, we will name the above useEffect as useEffect1.</p>
<p>Now let's start by drawing the snake and the fruit at a random position. Since we are going to draw the objects multiple times, we'll create a utility function called <code>drawObject</code> for it. Add the below code in the <code>utilities/index.tsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> interface IObjectBody {
  <span class="hljs-attr">x</span>: number;
  y: number;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> drawObject = <span class="hljs-function">(<span class="hljs-params">
  context: CanvasRenderingContext2D | <span class="hljs-literal">null</span>,
  objectBody: IObjectBody[],
  fillColor: string,
  strokeStyle = <span class="hljs-string">"#146356"</span>
</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (context) {
    objectBody.forEach(<span class="hljs-function">(<span class="hljs-params">object: IObjectBody</span>) =&gt;</span> {
      context.fillStyle = fillColor;
      context.strokeStyle = strokeStyle;
      context?.fillRect(object.x, object.y, <span class="hljs-number">20</span>, <span class="hljs-number">20</span>);
      context?.strokeRect(object.x, object.y, <span class="hljs-number">20</span>, <span class="hljs-number">20</span>);
    });
  }
};
</code></pre>
<p>The <code>drawObject</code> function accepts the following arguments:</p>
<ol>
<li><code>context</code> – A 2D canvas context object for drawing the object on the canvas.</li>
<li><code>objectBody</code> – This is an array of objects with each object having <code>x</code> and <code>y</code> properties, like the <code>IObjectBody</code> interface.</li>
<li><code>fillColor</code> – Color to be filled inside the object.</li>
<li><code>strokeStyle</code> – Color to be filled in the outline of the object. Defaults to <code>#146356</code>.</li>
</ol>
<p>This function will check if the context is undefined or null. Then it iterates over the <code>objectBody</code> via forEach. For each object it performs the following operations:</p>
<ol>
<li>It will assign the <code>fillStyle</code> and <code>strokeStyle</code> inside the context.</li>
<li>It will use <code>fillReact</code> to create a filled rectangle with coordinates <code>object.x</code> and <code>object.y</code> with size <code>20x20</code></li>
<li>Finally, it will use <code>strokeRect</code> to create an outlined rectangle with coordinates <code>object.x</code> and <code>object.y</code> with size <code>20x20</code> </li>
</ol>
<p>For drawing the snake we need to maintain the position of the snake. For that, we can use our global state management tool <code>redux</code>.</p>
<p>We need to update our <code>reducers/index.ts</code> file. Since we want to track the position of the snake, we will add it into our global state as follows:</p>
<pre><code class="lang-javascript">interface ISnakeCoord {
  <span class="hljs-attr">x</span>: number;
  y: number;
}

<span class="hljs-keyword">export</span> interface IGlobalState {
  <span class="hljs-attr">snake</span>: ISnakeCoord[] | [];
}

<span class="hljs-keyword">const</span> globalState: IGlobalState = {
  <span class="hljs-comment">//Postion of the entire snake</span>
  <span class="hljs-attr">snake</span>: [
    { <span class="hljs-attr">x</span>: <span class="hljs-number">580</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">560</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">520</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
  ],
};
</code></pre>
<p>Let's call this state in our <code>CanvasBoard</code> component. We will use the <code>useSelector</code> hook of react-redux to get the required state from the store. The following will give us the <code>snake</code>'s global state:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> snake1 = useSelector(<span class="hljs-function">(<span class="hljs-params">state: IGlobalState</span>) =&gt;</span> state.snake);
</code></pre>
<p>Let's embed this in our <code>CanvasBoard</code> component and pass it to our <code>drawObject</code> function and see the output:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//Importing necessary modules</span>
<span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { clearBoard, drawObject, generateRandomPosition } <span class="hljs-keyword">from</span> <span class="hljs-string">"../utils"</span>;

<span class="hljs-keyword">export</span> interface ICanvasBoard {
  <span class="hljs-attr">height</span>: number;
  width: number;
}

<span class="hljs-keyword">const</span> CanvasBoard = <span class="hljs-function">(<span class="hljs-params">{ height, width }: ICanvasBoard</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> canvasRef = useRef&lt;HTMLCanvasElement | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> [context, setContext] = useState&lt;CanvasRenderingContext2D | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> snake1 = useSelector(<span class="hljs-function">(<span class="hljs-params">state: IGlobalState</span>) =&gt;</span> state.snake);
    <span class="hljs-keyword">const</span> [pos, setPos] = useState&lt;IObjectBody&gt;(
        generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>)
      );

    useEffect(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">//Draw on canvas each time</span>
     setContext(canvasRef.current &amp;&amp; canvasRef.current.getContext(<span class="hljs-string">"2d"</span>)); <span class="hljs-comment">//store in state variable</span>
        drawObject(context, snake1, <span class="hljs-string">"#91C483"</span>); <span class="hljs-comment">//Draws snake at the required position</span>
        drawObject(context, [pos], <span class="hljs-string">"#676FA3"</span>); <span class="hljs-comment">//Draws fruit randomly</span>
    }, [context])

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">border:</span> "<span class="hljs-attr">3px</span> <span class="hljs-attr">solid</span> <span class="hljs-attr">black</span>",
      }}
      <span class="hljs-attr">height</span>=<span class="hljs-string">{height}</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">{width}</span>
    /&gt;</span></span>
  );
};
</code></pre>
<p>Let's see what the output will look like when the snake is drawn: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/snake_only.png" alt="Image" width="600" height="400" loading="lazy">
<em>Drawing snake</em></p>
<h2 id="heading-moving-the-snake-across-the-board">Moving the snake across the board</h2>
<p>Now that we have our snake drawn onto the canvas, let's learn how to move the snake across the board. </p>
<p>The movement of the snake is simple. It should always follow the below points:</p>
<ol>
<li>If the snake is moving horizontally, then it can only move up, down, and in the direction it is currently moving. For example, if the snake is moving to the right then it can move up or down or continue moving to the right.</li>
<li>If the snake is moving vertically, then it can only move to the right, left or continue in the direction it's currently moving. For example, if the snake is moving up then it can move right or left (or continue up).</li>
<li>The snake cannot move in the direction opposite to that of the current direction. That is, if the snake is moving to the left then it cannot move to the right straight away. Likewise, if it's going up it cannot move down.</li>
</ol>
<p>For the smooth movement of our snake, the snake should always move in a rectangular fashion. And it needs to meet the above points to have that movement. </p>
<p>The below diagram helps summarise how the movement of the snake works in the entire application:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/temp.png" alt="Image" width="600" height="400" loading="lazy">
<em>Snake movement explanation</em></p>
<p><strong>NOTE:</strong> In the above diagram, the entire movement of the snake starts with the <code>CanvasBoard</code> component. </p>
<p><strong>HINT:</strong> Don't worry if you cannot follow the above diagram. Just read the later sections to get more clarity.</p>
<p>To maintain the movement of the snake, we will introduce another state variable to our global state called <code>disallowedDirection</code>. The purpose of this variable is to keep track of the opposite direction of the snake's movement. </p>
<p>For example if the snake is moving left then the <code>disallowedDirection</code> will be set to right. So to summarise, we are tracking this direction so that we can avoid the snake moving in its opposite direction.</p>
<p>Let's create this variable in our global state:</p>
<pre><code class="lang-javascript">interface ISnakeCoord {
  <span class="hljs-attr">x</span>: number;
  y: number;
}

<span class="hljs-keyword">export</span> interface IGlobalState {
  <span class="hljs-attr">snake</span>: ISnakeCoord[] | [];
  disallowedDirection: string;
}

<span class="hljs-keyword">const</span> globalState: IGlobalState = {
    <span class="hljs-comment">//Postion of the entire snake</span>
  <span class="hljs-attr">snake</span>: [
    { <span class="hljs-attr">x</span>: <span class="hljs-number">580</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">560</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">520</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
  ],
    <span class="hljs-attr">disallowedDirection</span>: <span class="hljs-string">""</span>
};
</code></pre>
<p>Now let's create some actions and action creators that will help us move the snake. </p>
<p>We will have two types of actions for this case:</p>
<ul>
<li>Actions for sagas<ul>
<li>These are the actions that will be dispatched from the <code>CanvasBoard</code> component. These actions will be:<ul>
<li>MOVE_RIGHT</li>
<li>MOVE_LEFT</li>
<li>MOVE_UP</li>
<li>MOVE_DOWN</li>
</ul>
</li>
</ul>
</li>
<li>Actions for reducers<ul>
<li>These are the actions that will be yielded by the saga to propagate the calls to the reducers. These actions will be:<ul>
<li>RIGHT</li>
<li>LEFT</li>
<li>UP</li>
<li>DOWN</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>We will take a closer look at these actions in the coming sections.</p>
<p>We will be creating one more action called <code>SET_DIS_DIRECTION</code> to set the <code>disallowedDirection</code> state.</p>
<p>Let's create some action creators for the movement of the snake:</p>
<ul>
<li><code>setDisDirection</code> – This action creator will be used to set the <code>disallowedDirection</code> via the <code>SET_DIS_DIRECTION</code> action. Below is the code for this action creator:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> setDisDirection = <span class="hljs-function">(<span class="hljs-params">direction: string</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: SET_DIS_DIRECTION,
  <span class="hljs-attr">payload</span>: direction
});
</code></pre>
<ul>
<li><code>makeMove</code> – This will be used to set/update the new coordinates of the snake by updating the <code>snake</code> state variable. Below is the code for this action creator:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> makeMove = <span class="hljs-function">(<span class="hljs-params">dx: number, dy: number, move: string</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: move,
  <span class="hljs-attr">payload</span>: [dx, dy]
});
</code></pre>
<p>The parameters <code>dx</code> and <code>dy</code> are the deltas. They tell the Redux store by how much we should increase/decrease the coordinates of each snake block to move the snake in the given direction. </p>
<p>The <code>move</code> parameter is used to specify in which direction will the snake be moving. We will have a look at these actions creators soon in the coming sections.</p>
<p>Finally, our updated <code>actions/index.ts</code> file will look something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MOVE_RIGHT = <span class="hljs-string">"MOVE_RIGHT"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MOVE_LEFT = <span class="hljs-string">"MOVE_LEFT"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MOVE_UP = <span class="hljs-string">"MOVE_UP"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MOVE_DOWN = <span class="hljs-string">"MOVE_DOWN"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RIGHT = <span class="hljs-string">"RIGHT"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LEFT = <span class="hljs-string">"LEFT"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UP = <span class="hljs-string">"UP"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DOWN = <span class="hljs-string">"DOWN"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SET_DIS_DIRECTION = <span class="hljs-string">"SET_DIS_DIRECTION"</span>;

<span class="hljs-keyword">export</span> interface ISnakeCoord {
  <span class="hljs-attr">x</span>: number;
  y: number;
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> makeMove = <span class="hljs-function">(<span class="hljs-params">dx: number, dy: number, move: string</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: move,
  <span class="hljs-attr">payload</span>: [dx, dy]
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> setDisDirection = <span class="hljs-function">(<span class="hljs-params">direction: string</span>) =&gt;</span> ({
  <span class="hljs-attr">type</span>: SET_DIS_DIRECTION,
  <span class="hljs-attr">payload</span>: direction
});
</code></pre>
<p>Now, let's have a look at the logic we are using to move the snake based on the above actions. All the snake movement will be tracked by the following actions:</p>
<ul>
<li>RIGHT</li>
<li>LEFT</li>
<li>UP</li>
<li>DOWN</li>
</ul>
<p>All these actions are the building blocks of the snake's movement. These actions, when dispatched, will always update the <code>snake</code>'s global state based on the logic we are describing below. And they will calculate new coordinates of the snake on each movement.</p>
<p>To calculate the new coordinates of the snake after each movement, we will use the following logic:</p>
<ol>
<li>Copy the coordinates into a new variable called <code>newSnake</code></li>
<li>Add at the start of the <code>newSnake</code> the new x and y coordinates. These x and y attributes of these coordinates are updated by adding the x and y values from the action's payload.</li>
<li>Finally, remove the last entry from the <code>newSnake</code> array.</li>
</ol>
<p>Now that we have some understanding of how the snake is moving, let's add the following cases in our <code>gameReducer</code>:</p>
<pre><code class="lang-javascript">    <span class="hljs-keyword">case</span> RIGHT:
    <span class="hljs-keyword">case</span> LEFT:
    <span class="hljs-keyword">case</span> UP:
    <span class="hljs-keyword">case</span> DOWN: {
      <span class="hljs-keyword">let</span> newSnake = [...state.snake];
      newSnake = [{
        <span class="hljs-comment">//New x and y coordinates</span>
        <span class="hljs-attr">x</span>: state.snake[<span class="hljs-number">0</span>].x + action.payload[<span class="hljs-number">0</span>],
        <span class="hljs-attr">y</span>: state.snake[<span class="hljs-number">0</span>].y + action.payload[<span class="hljs-number">1</span>],
      }, ...newSnake];
      newSnake.pop();

      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">snake</span>: newSnake,
      };
    }
</code></pre>
<p>For every movement of the snake, we update the new x and y coordinates which are increased by payloads <code>action.payload[0]</code> and <code>action.payload[1]</code>. We successfully completed setting up the actions, actions creators, and the reducer logic. </p>
<p>We are good to go and can now use all of this in our <code>CanvasBoard</code> component.</p>
<p>First, let's add a useEffect hook in our <code>CanvasBoard</code> component. We will use this hook to attach/add an event handler. This event handler will be attached to the event <code>keypress</code>. We are using this event because whenever we press the <code>w</code> <code>a</code> <code>s</code> <code>d</code> keys we should be able to control the movement of the snake. </p>
<p>Our useEffect will look something like below:</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
    };
  }, [disallowedDirection, handleKeyEvents]);
</code></pre>
<p>It works in the following manner:</p>
<ol>
<li>On the mounting of the component, the event listener with callback function <code>handleKeyEvents</code> is attached to the window object.</li>
<li>On the unmounting of the component, the event listener is removed from the window object.</li>
<li>If there is any change in the direction or <code>handleKeyEvents</code> function, we will re-run this useEffect. Therefore, we have added <code>disallowedDirection</code> and <code>handleKeyEvents</code> into the dependency array.</li>
</ol>
<p>Let's have a look at how the <code>handleKeyEvents</code> callback is created. Below is the code for the same:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleKeyEvents = useCallback(
    <span class="hljs-function">(<span class="hljs-params">event: KeyboardEvent</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (disallowedDirection) {
        <span class="hljs-keyword">switch</span> (event.key) {
          <span class="hljs-keyword">case</span> <span class="hljs-string">"w"</span>:
            moveSnake(<span class="hljs-number">0</span>, <span class="hljs-number">-20</span>, disallowedDirection);
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"s"</span>:
            moveSnake(<span class="hljs-number">0</span>, <span class="hljs-number">20</span>, disallowedDirection);
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"a"</span>:
            moveSnake(<span class="hljs-number">-20</span>, <span class="hljs-number">0</span>, disallowedDirection);
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"d"</span>:
            event.preventDefault();
            moveSnake(<span class="hljs-number">20</span>, <span class="hljs-number">0</span>, disallowedDirection);
            <span class="hljs-keyword">break</span>;
        }
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">if</span> (
          disallowedDirection !== <span class="hljs-string">"LEFT"</span> &amp;&amp;
          disallowedDirection !== <span class="hljs-string">"UP"</span> &amp;&amp;
          disallowedDirection !== <span class="hljs-string">"DOWN"</span> &amp;&amp;
          event.key === <span class="hljs-string">"d"</span>
        )
          moveSnake(<span class="hljs-number">20</span>, <span class="hljs-number">0</span>, disallowedDirection); <span class="hljs-comment">//Move RIGHT at start</span>
      }
    },
    [disallowedDirection, moveSnake]
  );
</code></pre>
<p>We have wrapped this function with a <code>useCallback</code> hook. This is because we want the memoized version of this function which is called on every state change (that is, on the change of <code>disallowedDirection</code> and <code>moveSnake</code>).  This function is called on every key pressed on the keyboard. </p>
<p>This event handler callback function serves the following purpose:</p>
<ul>
<li>If the <code>disallowedDirection</code> is empty then we make sure that the game will start only when the user presses the <code>d</code> key. This means that the game starts only when the snake moves to the right. </li>
</ul>
<p><strong>NOTE</strong>: Initially the global state variable <code>disallowedDirection</code> value is an empty string. In this way, we know that if its value is empty then it's the start of the game.</p>
<p>Once the game starts, the <code>disallowedDirection</code> won’t be empty and then it listens to all the keyboard presses such as <code>w</code> <code>s</code> and <code>a</code>.</p>
<p>Finally, on every keypress, we are calling the function called <code>moveSnake</code>. We will take a closer look into it in the next section.</p>
<p>The <code>moveSnake</code> function is a function that dispatches an action passed to the <code>makeMove</code> action creator. This function accepts three arguments:</p>
<ol>
<li><strong>dx</strong> - <strong>Delta for x-axis</strong>. This tells by how much the snake should move along the x-axis. If <code>dx</code> is positive then it moves to the right, if it's negative it moves to the left.</li>
<li><strong>dy - Delta for the y-axis</strong>. This tells by how much the snake should move along the y-axis. If <code>dy</code> is positive then it moves down, if it's negative it moves up.</li>
<li><strong>disallowedDirection -</strong> This value tells that the snake should not move in the opposite direction. This is an action that is captured by our middleware saga.</li>
</ol>
<p>The code for the <code>moveSnake</code> function will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> moveSnake = useCallback(
    <span class="hljs-function">(<span class="hljs-params">dx = <span class="hljs-number">0</span>, dy = <span class="hljs-number">0</span>, ds: string</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (dx &gt; <span class="hljs-number">0</span> &amp;&amp; dy === <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"RIGHT"</span>) {
        dispatch(makeMove(dx, dy, MOVE_RIGHT));
      }

      <span class="hljs-keyword">if</span> (dx &lt; <span class="hljs-number">0</span> &amp;&amp; dy === <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"LEFT"</span>) {
        dispatch(makeMove(dx, dy, MOVE_LEFT));
      }

      <span class="hljs-keyword">if</span> (dx === <span class="hljs-number">0</span> &amp;&amp; dy &lt; <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"UP"</span>) {
        dispatch(makeMove(dx, dy, MOVE_UP));
      }

      <span class="hljs-keyword">if</span> (dx === <span class="hljs-number">0</span> &amp;&amp; dy &gt; <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"DOWN"</span>) {
        dispatch(makeMove(dx, dy, MOVE_DOWN));
      }
    },
    [dispatch]
  );
</code></pre>
<p>The <code>moveSnake</code> is a simple function that checks for the conditions:</p>
<ol>
<li>If dx &gt; 0, and the <code>disallowedDirection</code> is not <code>RIGHT</code>, then it can move in the RIGHT direction.</li>
<li>If dx &lt; 0, and the <code>disallowedDirection</code> is not <code>LEFT</code>, then it can move in the LEFT direction.</li>
<li>If dy &gt; 0, and the <code>disallowedDirection</code> is not <code>DOWN</code>, then it can move in the DOWN direction.</li>
<li>If dy &lt; 0, and the <code>disallowedDirection</code> is not <code>UP</code>, then it can move in the UP direction.</li>
</ol>
<p>This <code>disallowedDirection</code> value is set in our sagas which we'll talk about more in the later sections of this article. If we revisit the <code>handleKeyEvents</code> function now it makes much more sense. Let's walk through an example over here:</p>
<ul>
<li>Suppose you want to move the snake to the RIGHT. Then this function will detect that the <code>d</code> key is pressed.</li>
<li>Once this key is pressed it calls the <code>makeMove</code> function (Game start condition) with <code>dx</code> as 20 (+ve), <code>dy</code> as 0, and the previously set <code>disallowedDirection</code> previously is called over here.</li>
</ul>
<p>In this way, we make the movement of the snake in a particular direction. Now let's have a look at the <code>sagas</code> that we have used, and how they handle the movement of the snake.  </p>
<p>Let's create a file called <code>saga/index.ts</code>. This file will consist of all our sagas. This is not a rule, but in general, we create two sagas. </p>
<p>The first one is the saga which dispatches the actual actions to the store – let's call this <em>worker saga</em>. The second is the watcher saga which watches for any action that is being dispatched – let's call this <em>watcher saga</em>.</p>
<p>Now we need to create a watcher saga that will look out for the following actions: <code>MOVE_RIGHT</code>, <code>MOVE_LEFT</code>, <code>MOVE_UP</code>, <code>MOVE_DOWN</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watcherSaga</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">yield</span> takeLatest(
      [MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN],
      moveSaga
    ); 
}
</code></pre>
<p>This watcher saga will watch for the actions above and execute the <code>moveSaga</code> function which is a worker saga. </p>
<p>You will notice that we have used a new function named <code>takeLatest</code>. This function will call the worker saga and cancel any previous saga calls if any of the actions mentioned in the first argument are dispatched.</p>
<p>From the words of the redux-saga <a target="_blank" href="https://redux-saga.js.org/docs/api/#takelatestpattern-saga-args">docs</a>:</p>
<blockquote>
<p><code>takeLatest(pattern, saga, ...args)</code><a target="_blank" href="https://redux-saga.js.org/docs/api/#takelatestpattern-saga-args"></a></p>
<p>Forks a <code>saga</code> on each action dispatched to the Store that matches <code>pattern</code>. And automatically cancels any previous <code>saga</code> task started previously if it's still running.</p>
<ul>
<li>Each time an action is dispatched to the store. And if this action matches <code>pattern</code>, <code>takeLatest</code> starts a new <code>saga</code> task in the background. If a <code>saga</code> task was started previously (on the last action dispatched before the actual action), and if this task is still running, the task will be cancelled.</li>
<li><code>pattern: String | Array | Function</code> - for more information see docs for <code>[take(pattern)](https://redux-saga.js.org/docs/api/#takepattern)</code></li>
<li><code>saga: Function</code> - a Generator function</li>
<li><code>args: Array&lt;any&gt;</code> - arguments to be passed to the started task. <code>takeLatest</code> will add the incoming action to the argument list (i.e. the action will be the last argument provided to <code>saga</code>)</li>
</ul>
</blockquote>
<p>Now let's create a worker saga called <code>moveSaga</code> which will actually dispatch the actions to the Redux store:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">moveSaga</span>(<span class="hljs-params">params: {
    type: string;
    payload: ISnakeCoord;
  }</span>): <span class="hljs-title">Generator</span>&lt;
    | <span class="hljs-title">PutEffect</span>&lt;</span>{ type: string; payload: ISnakeCoord }&gt;
    | PutEffect&lt;{ <span class="hljs-attr">type</span>: string; payload: string }&gt;
    | CallEffect&lt;<span class="hljs-literal">true</span>&gt;
  &gt; {
    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
    <span class="hljs-comment">//dispatches movement actions</span>
     <span class="hljs-keyword">yield</span> put({
           <span class="hljs-attr">type</span>: params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>],
           <span class="hljs-attr">payload</span>: params.payload,
      }); 

      <span class="hljs-comment">//Dispatches SET_DIS_DIRECTION action</span>
      <span class="hljs-keyword">switch</span> (params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>]) {
        <span class="hljs-keyword">case</span> RIGHT:
          <span class="hljs-keyword">yield</span> put(setDisDirection(LEFT));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> LEFT:
          <span class="hljs-keyword">yield</span> put(setDisDirection(RIGHT));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> UP:
          <span class="hljs-keyword">yield</span> put(setDisDirection(DOWN));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> DOWN:
          <span class="hljs-keyword">yield</span> put(setDisDirection(UP));
          <span class="hljs-keyword">break</span>;
      }
      <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">100</span>);
    }
  }
</code></pre>
<p>The <code>moveSaga</code> worker saga performs the following functions:</p>
<ol>
<li>It executes inside an infinite loop. </li>
<li>So once a direction is given – that is if the <code>d</code> key is pressed and <code>MOVE_RIGHT</code> action is dispatched – then it starts dispatching the same action until a new action (that is, direction) is given. This is handled by the below snippet:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">yield</span> put({
    <span class="hljs-attr">type</span>: params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>],
    <span class="hljs-attr">payload</span>: params.payload,
});
</code></pre>
<ol start="3">
<li>Once the above action is dispatched we set the disallowed direction to the opposite direction which is taken care of by the action creator <code>setDisDirection</code>.</li>
</ol>
<p>Now let's stitch these sagas into our <code>sagas/index.ts</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {
    CallEffect,
    delay,
    put,
    PutEffect,
    takeLatest
} <span class="hljs-keyword">from</span> <span class="hljs-string">"redux-saga/effects"</span>;
<span class="hljs-keyword">import</span> {
    DOWN,
    ISnakeCoord,
    LEFT,
    MOVE_DOWN,
    MOVE_LEFT,
    MOVE_RIGHT,
    MOVE_UP, RIGHT,
    setDisDirection, UP
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;

  <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">moveSaga</span>(<span class="hljs-params">params: {
    type: string;
    payload: ISnakeCoord;
  }</span>): <span class="hljs-title">Generator</span>&lt;
    | <span class="hljs-title">PutEffect</span>&lt;</span>{ type: string; payload: ISnakeCoord }&gt;
    | PutEffect&lt;{ <span class="hljs-attr">type</span>: string; payload: string }&gt;
    | CallEffect&lt;<span class="hljs-literal">true</span>&gt;
  &gt; {
    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
      <span class="hljs-keyword">yield</span> put({
        <span class="hljs-attr">type</span>: params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>],
        <span class="hljs-attr">payload</span>: params.payload,
      });
      <span class="hljs-keyword">switch</span> (params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>]) {
        <span class="hljs-keyword">case</span> RIGHT:
          <span class="hljs-keyword">yield</span> put(setDisDirection(LEFT));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> LEFT:
          <span class="hljs-keyword">yield</span> put(setDisDirection(RIGHT));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> UP:
          <span class="hljs-keyword">yield</span> put(setDisDirection(DOWN));
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> DOWN:
          <span class="hljs-keyword">yield</span> put(setDisDirection(UP));
          <span class="hljs-keyword">break</span>;
      }
      <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">100</span>);
    }
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watcherSagas</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">yield</span> takeLatest(
      [MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN],
      moveSaga
    );
  }

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> watcherSagas;
</code></pre>
<p>Now let's update our <code>CanvasBoard</code> component to incorporate these changes.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//Importing necessary modules</span>
<span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { drawObject, generateRandomPosition } <span class="hljs-keyword">from</span> <span class="hljs-string">"../utils"</span>;

<span class="hljs-keyword">export</span> interface ICanvasBoard {
    <span class="hljs-attr">height</span>: number;
    width: number;
}

<span class="hljs-keyword">const</span> CanvasBoard = <span class="hljs-function">(<span class="hljs-params">{ height, width }: ICanvasBoard</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> canvasRef = useRef &lt; HTMLCanvasElement | <span class="hljs-literal">null</span> &gt; (<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> [context, setContext] = useState &lt; CanvasRenderingContext2D | <span class="hljs-literal">null</span> &gt; (<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> snake1 = useSelector(<span class="hljs-function">(<span class="hljs-params">state: IGlobalState</span>) =&gt;</span> state.snake);
    <span class="hljs-keyword">const</span> [pos, setPos] = useState &lt; IObjectBody &gt; (
        generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>)
    );

    <span class="hljs-keyword">const</span> moveSnake = useCallback(
        <span class="hljs-function">(<span class="hljs-params">dx = <span class="hljs-number">0</span>, dy = <span class="hljs-number">0</span>, ds: string</span>) =&gt;</span> {
            <span class="hljs-keyword">if</span> (dx &gt; <span class="hljs-number">0</span> &amp;&amp; dy === <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"RIGHT"</span>) {
                dispatch(makeMove(dx, dy, MOVE_RIGHT));
            }

            <span class="hljs-keyword">if</span> (dx &lt; <span class="hljs-number">0</span> &amp;&amp; dy === <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"LEFT"</span>) {
                dispatch(makeMove(dx, dy, MOVE_LEFT));
            }

            <span class="hljs-keyword">if</span> (dx === <span class="hljs-number">0</span> &amp;&amp; dy &lt; <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"UP"</span>) {
                dispatch(makeMove(dx, dy, MOVE_UP));
            }

            <span class="hljs-keyword">if</span> (dx === <span class="hljs-number">0</span> &amp;&amp; dy &gt; <span class="hljs-number">0</span> &amp;&amp; ds !== <span class="hljs-string">"DOWN"</span>) {
                dispatch(makeMove(dx, dy, MOVE_DOWN));
            }
        },
        [dispatch]
    );

    <span class="hljs-keyword">const</span> handleKeyEvents = useCallback(
        <span class="hljs-function">(<span class="hljs-params">event: KeyboardEvent</span>) =&gt;</span> {
            <span class="hljs-keyword">if</span> (disallowedDirection) {
                <span class="hljs-keyword">switch</span> (event.key) {
                    <span class="hljs-keyword">case</span> <span class="hljs-string">"w"</span>:
                        moveSnake(<span class="hljs-number">0</span>, <span class="hljs-number">-20</span>, disallowedDirection);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">"s"</span>:
                        moveSnake(<span class="hljs-number">0</span>, <span class="hljs-number">20</span>, disallowedDirection);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">"a"</span>:
                        moveSnake(<span class="hljs-number">-20</span>, <span class="hljs-number">0</span>, disallowedDirection);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">"d"</span>:
                        event.preventDefault();
                        moveSnake(<span class="hljs-number">20</span>, <span class="hljs-number">0</span>, disallowedDirection);
                        <span class="hljs-keyword">break</span>;
                }
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">if</span> (
                    disallowedDirection !== <span class="hljs-string">"LEFT"</span> &amp;&amp;
                    disallowedDirection !== <span class="hljs-string">"UP"</span> &amp;&amp;
                    disallowedDirection !== <span class="hljs-string">"DOWN"</span> &amp;&amp;
                    event.key === <span class="hljs-string">"d"</span>
                )
                    moveSnake(<span class="hljs-number">20</span>, <span class="hljs-number">0</span>, disallowedDirection); <span class="hljs-comment">//Move RIGHT at start</span>
            }
        },
        [disallowedDirection, moveSnake]
    );
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">//Draw on canvas each time</span>
        setContext(canvasRef.current &amp;&amp; canvasRef.current.getContext(<span class="hljs-string">"2d"</span>)); <span class="hljs-comment">//store in state variable</span>
                    clearBoard(context);
        drawObject(context, snake1, <span class="hljs-string">"#91C483"</span>); <span class="hljs-comment">//Draws snake at the required position</span>
    }, [context]);

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);

        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
        };
    }, [disallowedDirection, handleKeyEvents]);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
            <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
                <span class="hljs-attr">border:</span> "<span class="hljs-attr">3px</span> <span class="hljs-attr">solid</span> <span class="hljs-attr">black</span>",
            }}
            <span class="hljs-attr">height</span>=<span class="hljs-string">{height}</span>
            <span class="hljs-attr">width</span>=<span class="hljs-string">{width}</span>
        /&gt;</span></span>
    );
};
</code></pre>
<p>Once you've made these changes you can try moving the snake. And voilà! You will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/ezgif.com-gif-maker--3-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Moving snake across the board</em></p>
<h2 id="heading-drawing-the-fruit-at-a-random-position">Drawing the fruit at a random position</h2>
<p>To draw a fruit at a random position on the board we will use the <code>generateRandomPosition</code> utility function. Let's have a look at this function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">randomNumber</span>(<span class="hljs-params">min: number, max: number</span>) </span>{
  <span class="hljs-keyword">let</span> random = <span class="hljs-built_in">Math</span>.random() * max;
  <span class="hljs-keyword">return</span> random - (random % <span class="hljs-number">20</span>);
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> generateRandomPosition = <span class="hljs-function">(<span class="hljs-params">width: number, height: number</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">x</span>: randomNumber(<span class="hljs-number">0</span>, width),
    <span class="hljs-attr">y</span>: randomNumber(<span class="hljs-number">0</span>, height),
  };
};
</code></pre>
<p>This is a function that will generate random x and y coordinates in multiples of 20. These coordinates will always be less than the width and height of the board. It accepts <code>width</code> and <code>height</code> as arguments. </p>
<p>Once we have this function we can use it to draw the fruit at a random position inside the board. </p>
<p>First, let's create a state variable <code>pos</code> that will initially consist of some random position.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [pos, setPos] = useState&lt;IObjectBody&gt;(generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>));
</code></pre>
<p>Then, we will draw the fruit via our <code>drawObject</code> function. After this we will slightly update our <code>useEffect</code> hook:</p>
<pre><code class="lang-javascript"> useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">//Draw on canvas each time</span>
        setContext(canvasRef.current &amp;&amp;   canvasRef.current.getContext(<span class="hljs-string">"2d"</span>)); <span class="hljs-comment">//store in state variable</span>

        clearBoard(context);

        drawObject(context, snake1, <span class="hljs-string">"#91C483"</span>); <span class="hljs-comment">//Draws snake at the required position</span>

        drawObject(context, [pos], <span class="hljs-string">"#676FA3"</span>); <span class="hljs-comment">//Draws object randomly</span>
    }, [context]);
</code></pre>
<p>Once we have made the changes our board will look like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/snake_fruit.png" alt="Image" width="600" height="400" loading="lazy">
<em>Snake and fruit drawn on the board</em></p>
<h2 id="heading-score-calculator">Score calculator</h2>
<p>The game score is calculated based on how many fruits the snake has consumed without colliding with itself or with the boundary of the box. If the snake consumes the fruit then the size of the snake increases. If it collides with the edge of the box, then the game is over.  </p>
<p>Now that we know what our criteria are for calculating the score, let's have a look on how we calculate the reward.</p>
<h3 id="heading-calculating-the-reward">Calculating the reward</h3>
<p>The reward after the snake consumes the fruit is as follows:</p>
<ol>
<li>Increase the size of the snake.</li>
<li>Increase the score.</li>
<li>Place the new fruit at a different random location.</li>
</ol>
<p>If the snake consumes the fruit, then we must increase the size of the snake. This is a really simple task, we can just append the new x and y coordinates which are less than 20 from the last element of the <code>snake</code> global state array. For example, if the snake has the following coordinates:</p>
<pre><code class="lang-javascript">{
<span class="hljs-attr">snake</span>: [
    { <span class="hljs-attr">x</span>: <span class="hljs-number">580</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">560</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">520</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
  ],
}
</code></pre>
<p>We should simply append the following object into the snake array: <code>{ x: 480, y: 280 }</code></p>
<p>In this way, we increase the size of the snake as well as add the new part/block at the end of it. For this to be implemented via Redux and redux-saga, we will need the following action and action creator:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> INCREMENT_SCORE = <span class="hljs-string">"INCREMENT_SCORE"</span>; <span class="hljs-comment">//action</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> increaseSnake = <span class="hljs-function">() =&gt;</span> ({  <span class="hljs-comment">//action creator</span>
    <span class="hljs-attr">type</span>: INCREASE_SNAKE
  });
</code></pre>
<p>We will also update our <code>gameReducer</code> to accommodate these changes. We will add the following case:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">case</span> INCREASE_SNAKE:
      <span class="hljs-keyword">const</span> snakeLen = state.snake.length;
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">snake</span>: [
          ...state.snake,
          {
            <span class="hljs-attr">x</span>: state.snake[snakeLen - <span class="hljs-number">1</span>].x - <span class="hljs-number">20</span>,
            <span class="hljs-attr">y</span>: state.snake[snakeLen - <span class="hljs-number">1</span>].y - <span class="hljs-number">20</span>,
          },
        ],
      };
</code></pre>
<p>In our <code>CanvasBoard</code> component, we will first introduce a state variable called <code>isConsumed</code>. This variable will check if the fruit is consumed or not.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [isConsumed, setIsConsumed] = useState&lt;boolean&gt;(<span class="hljs-literal">false</span>);
</code></pre>
<p>In our <code>useEffect</code> hook where we are drawing our <code>snake</code> and the <code>fruit</code> just below that, we will add the following condition:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//When the object is consumed</span>
    <span class="hljs-keyword">if</span> (snake1[<span class="hljs-number">0</span>].x === pos?.x &amp;&amp; snake1[<span class="hljs-number">0</span>].y === pos?.y) {
      setIsConsumed(<span class="hljs-literal">true</span>);
    }
</code></pre>
<p>The above condition will check if the head of the snake <code>snake[0]</code> is equal to the <code>pos</code>, or the position of the fruit. If it is true, then it will set the <code>isConsumed</code> state variable to true.</p>
<p>Once the fruit is consumed, we need to increase the size of the snake. We can do this easily via another <code>useEffect</code>. Let's create another <code>useEffect</code> and call the action creator <code>increaseSnake</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//useEffect2</span>
useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (isConsumed) {
      <span class="hljs-comment">//Increase snake size when object is consumed successfully</span>
      dispatch(increaseSnake());
    }
  }, [isConsumed]);
</code></pre>
<p>Now that we have increased the size of the snake, let's take a look at how we can update the score and generate a new fruit at another random position.</p>
<p>To generate a new fruit at another random position, we update the <code>pos</code> state variable which will re-run the useEffect1 and draw the object at <code>pos</code>. We should update our useEffect1 with a new dependency of <code>pos</code> and update useEffect2 as follows:</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//Generate new object</span>
    <span class="hljs-keyword">if</span> (isConsumed) {
      <span class="hljs-keyword">const</span> posi = generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>);
      setPos(posi);
      setIsConsumed(<span class="hljs-literal">false</span>);

      <span class="hljs-comment">//Increase snake size when object is consumed successfully</span>
      dispatch(increaseSnake());
    }
  }, [isConsumed, pos, height, width, dispatch]);
</code></pre>
<p>One last thing left to do in this reward system is to update the score each time the snake eats the fruit. To do this follow the below steps:</p>
<ol>
<li>Introduce a new global state variable called <code>score</code>. Update our global state as below in the <code>reducers/index.ts</code> file:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> interface IGlobalState {
  <span class="hljs-attr">snake</span>: ISnakeCoord[] | [];
  disallowedDirection: string;
  score: number;
}

<span class="hljs-keyword">const</span> globalState: IGlobalState = {
  <span class="hljs-attr">snake</span>: [
    { <span class="hljs-attr">x</span>: <span class="hljs-number">580</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">560</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">520</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
    { <span class="hljs-attr">x</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">300</span> },
  ],
  <span class="hljs-attr">disallowedDirection</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">score</span>: <span class="hljs-number">0</span>,
};
</code></pre>
<ol start="2">
<li>Create the following action and action creator in our <code>actions/index.ts</code> file:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> INCREMENT_SCORE = <span class="hljs-string">"INCREMENT_SCORE"</span>; <span class="hljs-comment">//action</span>

<span class="hljs-comment">//action creator:</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> scoreUpdates = <span class="hljs-function">(<span class="hljs-params">type: string</span>) =&gt;</span> ({
  type
});
</code></pre>
<ol start="3">
<li>Next, update our reducer to handle the <code>INCREMENT_SCORE</code> action. This will simply increment the global state <code>score</code> by one.</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">case</span> INCREMENT_SCORE:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">score</span>: state.score + <span class="hljs-number">1</span>,
      };
</code></pre>
<ol start="4">
<li>Then we update our score state, dispatching the <code>INCREMENT_SCORE</code> action each time snake catches the fruit. For this we can update our useEffect2 as follows:</li>
</ol>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//Generate new object</span>
    <span class="hljs-keyword">if</span> (isConsumed) {
      <span class="hljs-keyword">const</span> posi = generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>);
      setPos(posi);
      setIsConsumed(<span class="hljs-literal">false</span>);

      <span class="hljs-comment">//Increase snake size when object is consumed successfully</span>
      dispatch(increaseSnake());

      <span class="hljs-comment">//Increment the score</span>
      dispatch(scoreUpdates(INCREMENT_SCORE));
    }
  }, [isConsumed, pos, height, width, dispatch]);
</code></pre>
<ol start="5">
<li>Finally, we create a component called <code>ScoreCard</code>. This will display the player’s current score. We will store this in the file <code>components/ScoreCard.tsx</code>.</li>
</ol>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Heading } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
<span class="hljs-keyword">import</span> { IGlobalState } <span class="hljs-keyword">from</span> <span class="hljs-string">"../store/reducers"</span>;

<span class="hljs-keyword">const</span> ScoreCard = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> score = useSelector(<span class="hljs-function">(<span class="hljs-params">state: IGlobalState</span>) =&gt;</span> state.score);
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h2"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"md"</span> <span class="hljs-attr">mt</span>=<span class="hljs-string">{5}</span> <span class="hljs-attr">mb</span>=<span class="hljs-string">{5}</span>&gt;</span>Current Score: {score}<span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ScoreCard;
</code></pre>
<p>After this we should also add the <code>ScoreCard</code> component into the <code>App.tsx</code> file to display it on our page. </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { ChakraProvider, Container, Heading } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/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> CanvasBoard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/CanvasBoard"</span>;
<span class="hljs-keyword">import</span> ScoreCard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/ScoreCard"</span>;
<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">"./store"</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">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">ChakraProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Container</span> <span class="hljs-attr">maxW</span>=<span class="hljs-string">"container.lg"</span> <span class="hljs-attr">centerContent</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h1"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"xl"</span>&gt;</span>SNAKE GAME<span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ScoreCard</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">CanvasBoard</span> <span class="hljs-attr">height</span>=<span class="hljs-string">{600}</span> <span class="hljs-attr">width</span>=<span class="hljs-string">{1000}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Once everything is in place, our snake will have a complete reward system that increases the size of the snake to update the score.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/ezgif.com-gif-maker--4-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Player playing snake with updating score and snake length.</em></p>
<h3 id="heading-collision-detection">Collision detection</h3>
<p>In this section, we are going to take a look at how we implement collision detection for our Snake game.</p>
<p>In our Snake game, if a collision is detected, then the game is over – that is, the game stops. There are two conditions for collisions to happen:</p>
<ol>
<li>Snake collides with the boundaries of the box, or</li>
<li>Snake collides with itself.</li>
</ol>
<p>Let's take a look at the first condition. Suppose the head of the snake touches the boundaries of the box. In that case we will immediately stop the game. </p>
<p>For this to be incorporated into our game we will need to do as follows:</p>
<ol>
<li>Create an action and an action creator as below:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> STOP_GAME = <span class="hljs-string">"STOP_GAME"</span>; <span class="hljs-comment">//action</span>

<span class="hljs-comment">//action creator</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> stopGame = <span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">type</span>: STOP_GAME
});
</code></pre>
<ol start="2">
<li>We need to update our <code>sagas/index.ts</code> file as well. We are going to make sure that saga stops dispatching actions once the <code>STOP_GAME</code> action is encountered.</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">moveSaga</span>(<span class="hljs-params">params: {
  type: string;
  payload: ISnakeCoord;
}</span>): <span class="hljs-title">Generator</span>&lt;
  | <span class="hljs-title">PutEffect</span>&lt;</span>{ type: string; payload: ISnakeCoord }&gt;
  | PutEffect&lt;{ <span class="hljs-attr">type</span>: string; payload: string }&gt;
  | CallEffect&lt;<span class="hljs-literal">true</span>&gt;
&gt; {
  <span class="hljs-keyword">while</span> (params.type !== STOP_GAME) {
    <span class="hljs-keyword">yield</span> put({
      <span class="hljs-attr">type</span>: params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>],
      <span class="hljs-attr">payload</span>: params.payload,
    });
    <span class="hljs-keyword">switch</span> (params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>]) {
      <span class="hljs-keyword">case</span> RIGHT:
        <span class="hljs-keyword">yield</span> put(setDisDirection(LEFT));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> LEFT:
        <span class="hljs-keyword">yield</span> put(setDisDirection(RIGHT));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> UP:
        <span class="hljs-keyword">yield</span> put(setDisDirection(DOWN));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> DOWN:
        <span class="hljs-keyword">yield</span> put(setDisDirection(UP));
        <span class="hljs-keyword">break</span>;
    }
    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">100</span>);
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watcherSagas</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> takeLatest(
    [MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN, STOP_GAME],
    moveSaga
  );
}
</code></pre>
<ol start="3">
<li>Finally we need to update our useEffect1 by adding the following condition:</li>
</ol>
<pre><code class="lang-jsx"><span class="hljs-keyword">if</span> ( <span class="hljs-comment">//Checks if the snake head is out of the boundries of the obox</span>
      snake1[<span class="hljs-number">0</span>].x &gt;= width ||
      snake1[<span class="hljs-number">0</span>].x &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &gt;= height
    ) {
      setGameEnded(<span class="hljs-literal">true</span>);
      dispatch(stopGame());
      <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
    }
</code></pre>
<p>We are also removing the event listener <code>handleKeyEvents</code>. This will make sure that once the game is over the player cannot move the snake.</p>
<p>Finally, let's have a look at how we can detect the self-collision of the snake. We are going to use a utility function called <code>hasSnakeCollided</code>. It accepts two parameters: the first is the snake array, and the second is the head of the snake. If the head of the snake touches any parts of itself then it returns true or else it returns false.</p>
<p>The <code>hasSnakeCollided</code> function will look like below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> hasSnakeCollided = <span class="hljs-function">(<span class="hljs-params">
  snake: IObjectBody[],
  currentHeadPos: IObjectBody
</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> flag = <span class="hljs-literal">false</span>;
  snake.forEach(<span class="hljs-function">(<span class="hljs-params">pos: IObjectBody, index: number</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (
      pos.x === currentHeadPos.x &amp;&amp;
      pos.y === currentHeadPos.y &amp;&amp;
      index !== <span class="hljs-number">0</span>
    ) {
      flag = <span class="hljs-literal">true</span>;
    }
  });

  <span class="hljs-keyword">return</span> flag;
};
</code></pre>
<p>We might slightly need to update our useEffect1 by updating the collision detection condition like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (  
      <span class="hljs-comment">//Checks if the snake has collided with itself </span>
      hasSnakeCollided(snake1, snake1[<span class="hljs-number">0</span>]) ||

      <span class="hljs-comment">//Checks if the snake head is out of the boundries of the obox</span>
      snake1[<span class="hljs-number">0</span>].x &gt;= width ||
      snake1[<span class="hljs-number">0</span>].x &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &gt;= height
    ) {
      setGameEnded(<span class="hljs-literal">true</span>);
      dispatch(stopGame());
      <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
    }
</code></pre>
<p>Our useEffect1 will finally look like below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//useEffect1</span>
useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//Draw on canvas each time</span>
    setContext(canvasRef.current &amp;&amp; canvasRef.current.getContext(<span class="hljs-string">"2d"</span>));
    clearBoard(context);
    drawObject(context, snake1, <span class="hljs-string">"#91C483"</span>);
    drawObject(context, [pos], <span class="hljs-string">"#676FA3"</span>); <span class="hljs-comment">//Draws object randomly</span>

    <span class="hljs-comment">//When the object is consumed</span>
    <span class="hljs-keyword">if</span> (snake1[<span class="hljs-number">0</span>].x === pos?.x &amp;&amp; snake1[<span class="hljs-number">0</span>].y === pos?.y) {
      setIsConsumed(<span class="hljs-literal">true</span>);
    }

    <span class="hljs-keyword">if</span> (
      hasSnakeCollided(snake1, snake1[<span class="hljs-number">0</span>]) ||
      snake1[<span class="hljs-number">0</span>].x &gt;= width ||
      snake1[<span class="hljs-number">0</span>].x &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &lt;= <span class="hljs-number">0</span> ||
      snake1[<span class="hljs-number">0</span>].y &gt;= height
    ) {
      setGameEnded(<span class="hljs-literal">true</span>);
      dispatch(stopGame());
      <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
    } <span class="hljs-keyword">else</span> setGameEnded(<span class="hljs-literal">false</span>);
  }, [context, pos, snake1, height, width, dispatch, handleKeyEvents]);
</code></pre>
<p>Our game will look like below once we add the collision detection system:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/ezgif.com-gif-maker--5-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Collision detection</em></p>
<h2 id="heading-instruction-component">Instruction component</h2>
<p>We are in the end game now! Our final component will be the <code>Instruction</code> component. It will consist of instructions about the game like initial game condition, keys to use, and a reset button. </p>
<p>Let's start by creating a file called <code>components/Instructions.tsx</code>. Place the below code in this file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Box, Button, Flex, Heading, Kbd } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

<span class="hljs-keyword">export</span> interface IInstructionProps {
  <span class="hljs-attr">resetBoard</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">void</span>;
}
<span class="hljs-keyword">const</span> Instruction = <span class="hljs-function">(<span class="hljs-params">{ resetBoard }: IInstructionProps</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">mt</span>=<span class="hljs-string">{3}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h6"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"lg"</span>&gt;</span>
      How to Play
    <span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h5"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"sm"</span> <span class="hljs-attr">mt</span>=<span class="hljs-string">{1}</span>&gt;</span>
    NOTE: Start the game by pressing <span class="hljs-tag">&lt;<span class="hljs-name">Kbd</span>&gt;</span>d<span class="hljs-tag">&lt;/<span class="hljs-name">Kbd</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span> <span class="hljs-attr">flexDirection</span>=<span class="hljs-string">"row"</span> <span class="hljs-attr">mt</span>=<span class="hljs-string">{3}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span> <span class="hljs-attr">flexDirection</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">column</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Kbd</span>&gt;</span>w<span class="hljs-tag">&lt;/<span class="hljs-name">Kbd</span>&gt;</span> Move Up
        <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>
          <span class="hljs-tag">&lt;<span class="hljs-name">Kbd</span>&gt;</span>a<span class="hljs-tag">&lt;/<span class="hljs-name">Kbd</span>&gt;</span> Move Left
        <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>
          <span class="hljs-tag">&lt;<span class="hljs-name">Kbd</span>&gt;</span>s<span class="hljs-tag">&lt;/<span class="hljs-name">Kbd</span>&gt;</span> Move Down
        <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>
          <span class="hljs-tag">&lt;<span class="hljs-name">Kbd</span>&gt;</span>d<span class="hljs-tag">&lt;/<span class="hljs-name">Kbd</span>&gt;</span> Move Right
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span> <span class="hljs-attr">flexDirection</span>=<span class="hljs-string">"column"</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> resetBoard()}&gt;Reset game<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Instruction;
</code></pre>
<p>The <code>Instruction</code> component will accept <code>resetBoard</code> as a prop which is a function that will help the user when the game is over or when they want to reset the game.</p>
<p>Before we dive into the <code>resetBoard</code> function we need to make the following updates in our Redux store and saga:</p>
<ol>
<li>Add the following action and action creator in the <code>actions/index.ts</code> file:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RESET_SCORE = <span class="hljs-string">"RESET_SCORE"</span>; <span class="hljs-comment">//action</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RESET = <span class="hljs-string">"RESET"</span>; <span class="hljs-comment">//action</span>

<span class="hljs-comment">//Action creator:</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> resetGame = <span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">type</span>: RESET
});
</code></pre>
<ol start="2">
<li>Then add the following condition into our <code>sagas/index.ts</code>. We are going to make sure that saga discontinues to dispatch actions once the <code>RESET</code> and the <code>STOP_GAME</code> actions are encountered.</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">moveSaga</span>(<span class="hljs-params">params: {
  type: string;
  payload: ISnakeCoord;
}</span>): <span class="hljs-title">Generator</span>&lt;
  | <span class="hljs-title">PutEffect</span>&lt;</span>{ type: string; payload: ISnakeCoord }&gt;
  | PutEffect&lt;{ <span class="hljs-attr">type</span>: string; payload: string }&gt;
  | CallEffect&lt;<span class="hljs-literal">true</span>&gt;
&gt; {
  <span class="hljs-keyword">while</span> (params.type !== RESET &amp;&amp; params.type !== STOP_GAME) {
    <span class="hljs-keyword">yield</span> put({
      <span class="hljs-attr">type</span>: params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>],
      <span class="hljs-attr">payload</span>: params.payload,
    });
    <span class="hljs-keyword">switch</span> (params.type.split(<span class="hljs-string">"_"</span>)[<span class="hljs-number">1</span>]) {
      <span class="hljs-keyword">case</span> RIGHT:
        <span class="hljs-keyword">yield</span> put(setDisDirection(LEFT));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> LEFT:
        <span class="hljs-keyword">yield</span> put(setDisDirection(RIGHT));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> UP:
        <span class="hljs-keyword">yield</span> put(setDisDirection(DOWN));
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">case</span> DOWN:
        <span class="hljs-keyword">yield</span> put(setDisDirection(UP));
        <span class="hljs-keyword">break</span>;
    }
    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">100</span>);
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">watcherSagas</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> takeLatest(
    [MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN, RESET, STOP_GAME],
    moveSaga
  );
}
</code></pre>
<ol start="3">
<li>Finally, we update our <code>reducers/index.ts</code> file for the <code>RESET_SCORE</code> case as follows:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">case</span> RESET_SCORE:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">score</span>: <span class="hljs-number">0</span> };
</code></pre>
<p>Once our sagas and reducers are updated we can take a look at what operations the <code>resetBoard</code> callback will perform.</p>
<p>The <code>resetBoard</code> function performs the following operations:</p>
<ol>
<li>Removes the event listener <code>handleKeyEvents</code></li>
<li>dispatches the actions necessary for resetting the game.</li>
<li>Dispatches the action to reset the score.</li>
<li>Clears the canvas.</li>
<li>Draws the snake again at its initial position</li>
<li>Draws the fruit at a new random position.</li>
<li>Finally, adds the event listener <code>handleKeyEvents</code> for the <code>keypress</code> event.</li>
</ol>
<p>Below is how our <code>resetBoard</code> function will look:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> resetBoard = useCallback(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
    dispatch(resetGame());
    dispatch(scoreUpdates(RESET_SCORE));
    clearBoard(context);
    drawObject(context, snake1, <span class="hljs-string">"#91C483"</span>);
    drawObject(
      context,
      [generateRandomPosition(width - <span class="hljs-number">20</span>, height - <span class="hljs-number">20</span>)],
      <span class="hljs-string">"#676FA3"</span>
    ); <span class="hljs-comment">//Draws object randomly</span>
    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"keypress"</span>, handleKeyEvents);
  }, [context, dispatch, handleKeyEvents, height, snake1, width]);
</code></pre>
<p>You should place this function inside the <code>CanvasBoard</code> component and pass the <code>resetBoard</code> function as a prop to the <code>Instruction</code> function as below:</p>
<pre><code class="lang-jsx">&lt;&gt;
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
        <span class="hljs-attr">ref</span>=<span class="hljs-string">{canvasRef}</span>
        <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
          <span class="hljs-attr">border:</span> `<span class="hljs-attr">3px</span> <span class="hljs-attr">solid</span> ${<span class="hljs-attr">gameEnded</span> ? "<span class="hljs-attr">red</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">black</span>"}`,
        }}
        <span class="hljs-attr">width</span>=<span class="hljs-string">{width}</span>
        <span class="hljs-attr">height</span>=<span class="hljs-string">{height}</span>
      /&gt;</span></span>
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Instruction</span> <span class="hljs-attr">resetBoard</span>=<span class="hljs-string">{resetBoard}</span> /&gt;</span></span>
    &lt;/&gt;
</code></pre>
<p>Once this is placed we will have the Instruction component set up like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Instructions with reset button</em></p>
<h2 id="heading-final-game">Final Game</h2>
<p>If you have followed along up to this point, then congrats! You have successfully created a fun Snake game with React, Redux and redux-sagas. Once all of these things are connected your game will look like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/ezgif.com-gif-maker--2--1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The complete snake game</em></p>
<h2 id="heading-summary">Summary</h2>
<p>So this is how you can build a Snake game from scratch. You can find the entire source code for the game in the below repository:</p>
<p><a target="_blank" href="https://github.com/keyurparalkar/snake-game">https://github.com/keyurparalkar/snake-game</a></p>
<p>If you liked the idea of building your own Snake game from scratch then you can take it up a notch by building these enhancements:</p>
<ul>
<li>Build the snake game with three.js</li>
<li>Add an online score board</li>
</ul>
<p>Thank you for reading!</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/keurplkar">Twitter</a>, <a target="_blank" href="https://github.com/keyurparalkar">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/keyur-paralkar-494415107/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Redux for Application-Wide State Management ]]>
                </title>
                <description>
                    <![CDATA[ By Prajwal Kulkarni Let's face it – state management across multiple components isn't easy. Sometimes we might set up the state or logic handling properly, but fail to consume the states. Or we might get everything working, but clutter up the codebas... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-redux-for-application-wide-state-management/</link>
                <guid isPermaLink="false">66d4608ff855545810e934b7</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 02 Dec 2021 15:47:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/React-redux-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Prajwal Kulkarni</p>
<p>Let's face it – state management across multiple components isn't easy.</p>
<p>Sometimes we might set up the state or logic handling properly, but fail to consume the states. Or we might get everything working, but clutter up the codebase in the process, making it hard to read, adapt, and extend.  </p>
<p>The ability to have a single source of truth (a single store) is what gives Redux an upper hand over the traditional Context API.</p>
<p>So, without any further ado, let's see how we can make the best use of Redux for application-wide state management by writing cleaner and more optimized code.</p>
<h2 id="heading-before-we-start">Before We Start</h2>
<p>This article mainly looks at different ways to improve an existing Redux store. So you'll need to know the basics of Redux to get through it, such as setting up reducers, the Redux store, and dispatching actions.</p>
<p>If you need to brush up on Redux, check out these helpful guides:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners/">Redux for Beginners</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners-the-brain-friendly-guide-to-redux/">The Brain-friendly Guide to Learning Redux</a></li>
</ul>
<p>Already know the basics of Redux and have a Redux store you want to improve? Good.</p>
<p>Here's what we'll cover in this article:</p>
<ul>
<li>A quick recap on how to use the Redux store</li>
<li>How to use the Redux Toolkit library by creating a Redux store for an e-commerce application. Note: we won't build the entire application, but just the state management part of it</li>
<li>How to handle asynchronous code outside of reduces and components by using action creators</li>
</ul>
<p>And with that, let's get started.</p>
<h2 id="heading-a-quick-redux-store-recap">A Quick Redux Store Recap</h2>
<p>Before looking at how we can improve our Redux code, let's have a brief look at how we've been using Redux up to this point.</p>
<p>Here's a basic example of a Redux store. It's for a simple counter application that can increment and decrement the count on button clicks, and the state of the counter is managed and handled by Redux:</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-keyword">const</span> initialState = {
  <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span>,
}

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> { <span class="hljs-comment">// Reducer function</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">counter</span>: state.counter + <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">counter</span>: state.counter - <span class="hljs-number">1</span> }
    <span class="hljs-attr">default</span>:
      <span class="hljs-keyword">return</span> state
  }
}

<span class="hljs-keyword">const</span> store = createStore(reducer) <span class="hljs-comment">// redux-store</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store
</code></pre>
<pre><code class="lang-javascript"><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">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Component</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">const</span> dispatch = useDispatch()
  <span class="hljs-keyword">const</span> counter = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.counter)

  <span class="hljs-keyword">const</span> incrementHandler = <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> decrementHandler = <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">h1</span>&gt;</span>Counter:{counter}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{incrementHandler}</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">{decrementHandler}</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>
  )
}
</code></pre>
<p>This is a very simple example that you could create just using state hooks. But it serves as a good overview of how we'd typically use Redux.</p>
<p>The Redux store above is perfectly fine if there aren't many different types of logic that need to be handled or dispatched.</p>
<p>Also, note that I used <code>const initialState</code> instead of <code>var</code> or <code>let</code> even though we are updating the state because of the property of immutability. That is, we aren't really mutating the existing state, but instead are reconstructing a new state altogether with the updated values.</p>
<p>This is fine. But what if the complexity of the application grows and requires us to perform multiple state and logic handling?</p>
<p>That's exactly what we'll cover in this guide.</p>
<h2 id="heading-how-to-create-a-redux-store-with-redux-toolkit">How to Create a Redux Store With Redux Toolkit</h2>
<p>Throughout the rest of the article, let's consider how to manage state across an e-commerce application. In an e-commerce app, we would want to track and broadcast multiple states across various components.</p>
<p>As a rule of thumb, it is always good to have a rough idea of how we'll implement a design prior to getting our hands dirty.</p>
<p>When we think of an e-commerce application, the possible significant states are likely the following:</p>
<ol>
<li>Authentication</li>
<li>Cart tracking</li>
<li>Watchlist</li>
</ol>
<p>We can divide the state handling logic and the state into different modules, and then combine it all into a single store.</p>
<p>For this, we'll use Redux Toolkit.</p>
<p>Redux Toolkit is a third-party library like Redux, created and maintained by the Redux team.</p>
<p>You might be wondering why the Redux team created Redux Toolkit in the first place. The answer is right at the beginning of the <a target="_blank" href="https://redux-toolkit.js.org/introduction/getting-started">documentation</a>:</p>
<blockquote>
<p>The Redux Toolkit package is intended to be the standard way to write Redux logic. It was originally created to help address three common concerns about Redux:  </p>
<ul>
<li>"Configuring a Redux store is too complicated"  </li>
<li>"I have to add a lot of packages to get Redux to do anything useful"  </li>
<li>"Redux requires too much boilerplate code"</li>
</ul>
</blockquote>
<p>All-in-all, the whole point of using Redux Toolkit is to make using Redux easier and more efficient.</p>
<h3 id="heading-how-to-install-redux-toolkit">How to Install Redux Toolkit</h3>
<p>You can install Redux Toolkit either with <code>npm</code> or <code>yarn</code> like this:</p>
<ul>
<li><code>npm install @reduxjs/toolkit</code></li>
<li><code>yard add @reduxjs/toolkit</code></li>
</ul>
<h2 id="heading-how-to-use-redux-toolkit">How to Use Redux Toolkit</h2>
<p>The first stop when creating a Redux store is to set up state handling.</p>
<p>Instead of using reducers, we'll use <code>createSlice</code> which is provided by Redux Toolkit.</p>
<p><code>createSlice</code> accepts 3 mandatory arguments, which are:</p>
<ol>
<li><strong>name</strong>: the name of the slice</li>
<li><strong>initialState</strong>: the initial state of the slice (This is like the initial state of a reducer)</li>
<li><strong>reducers</strong>: functions that affect the states (actions)</li>
</ol>
<p>A slice, in brief, is like a modularized bundler of states and their actions.</p>
<p>Let's begin by creating a slice for authentication and its related actions:</p>
<pre><code><span class="hljs-keyword">const</span> authSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Auth'</span>, <span class="hljs-comment">// Could name it anything</span>
  <span class="hljs-attr">initialState</span>: {
    <span class="hljs-attr">isLoggedIn</span>: <span class="hljs-literal">false</span>,
  },
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">login</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      state.isLoggedIn = <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">logout</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      state.isLoggedIn = <span class="hljs-literal">false</span>
    },
  },
})
</code></pre><p>As you can see, the slice above is dedicated to user authentication. <code>initialState</code> is an object that contains different initial state values, and the states that the reducers need to act upon. The functions in reducers are like regular reducers that accept state and action as arguments. </p>
<p>One noticeable catch in the above snippet is how we're are dealing with updating the state with <code>state.isLoggedIn = true</code>. This is clearly mutating the state, violating the property of immutability.</p>
<p>Or, is it?</p>
<p>Let's understand what's happening under the hood before jumping to conclusions.</p>
<p>On the surface it seems like we're mutating the existing state. But mutating the existing state wouldn't trigger the broadcasting of updated value(s) to the subscribers.</p>
<p>So when we use mutating syntax in the reduces, <code>createSlice</code> uses a library called <a target="_blank" href="https://redux-toolkit.js.org/usage/immer-reducers">Immer</a> internally. This library draws the difference in the existing and the updated state, and reconstructs a new object with an updated value.</p>
<p>This means that, when we mutate the state, Immer takes care of building a new object and conforming to the property of immutability, making it easier for us to write code.</p>
<p>Now, let's write the slices for the other states:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> cartSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Cart'</span>,
  <span class="hljs-attr">initialState</span>: {
    <span class="hljs-attr">cart</span>: [],
    <span class="hljs-attr">qty</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
  },
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.cart.push(action.payload.cartItem)
      state.qty += action.payload.cartItem.qty
      state.total += action.payload.cartItem.price * action.payload.cartItem.qty
    },
    <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> itemIndex = state.cart.findIndex(
        <span class="hljs-function">(<span class="hljs-params">obj</span>) =&gt;</span> obj.id === action.payload.id
      )
      <span class="hljs-keyword">if</span> (itemIndex !== <span class="hljs-number">-1</span> &amp;&amp; state.cart[itemIndex].qty &gt;= <span class="hljs-number">1</span>) {
        state.cart[itemIndex].qty -= <span class="hljs-number">1</span>
      }
    }
  }
})
</code></pre>
<p>The major part here is the logic related to adding and removing items from the cart.</p>
<p>We follow a similar logic for a watchlist, but without the total quantity and total cost:</p>
<pre><code><span class="hljs-keyword">const</span> watchlistSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Watchlist'</span>,
  <span class="hljs-attr">initialState</span>: {
    <span class="hljs-attr">watchlist</span>: [],
  },
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">addItem</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.watchlist.push(action.payload.watchlistItem)
    },
    <span class="hljs-attr">removeItem</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      state.watchlist.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id !== action.payload.id)
    }
  }
})
</code></pre><p>Notice how the action item is accessed via the payload property, and not directly.</p>
<p>This is because the Redux Toolkit adds the <code>payload</code> property on actions by default. <code>payload</code> is an object which can further contain other nested objects, or simple key-value pairs. It basically holds the arguments passed to the action dispatcher.</p>
<p>Now you might be asking yourself, how are we actually going to dispatch the action(s)?</p>
<p>Prior to using Redux Toolkit, we used to perform actions based on the action <code>type</code>. Then depending upon the <code>type</code> we would perform different operations.</p>
<p>But here we aren't using any <code>type</code> property, because we'll be exporting the reducer functions as actions, which could then be invoked within the dispatcher.</p>
<p>Reducer functions can by exported as actions by calling the <code>actions</code> property on the created slice:</p>
<p><code>export const authActions = authSlice.actions</code></p>
<p><code>export const cartActions = cartSlice.actions</code></p>
<p><code>export const wathclistActions = watchlistSlice.actions</code></p>
<p>All the slices here are not directly related to each other, so it's safe and also good practice to have them in separate files.</p>
<p>If you add slices to different files, make sure to export them as well.</p>
<h3 id="heading-how-to-combine-slices-into-a-single-store">How to Combine Slices Into a Single Store</h3>
<p>A store can have only one reducer, so it is important to combine all the slices and their reducers into a single reducer without losing its identity and functionality.</p>
<p>To accomplish this, we'll use <code>configureStore</code> to <code>createStore</code>.</p>
<p><code>configureStore</code> is similar to <code>createStore</code>, but it can merge reducers of multiple slices into a single reducer.</p>
<p>It has a <code>reducer</code> object that accepts one or more slices, like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { authSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth-slice'</span>
<span class="hljs-keyword">import</span> { cartSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'./cart-slice'</span>
<span class="hljs-keyword">import</span> { wathclistSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'./watchlist-slice'</span>

<span class="hljs-keyword">const</span> store = configureStore({
  <span class="hljs-attr">reducer</span>: {
    <span class="hljs-attr">authSliceReducer</span>: authSlice.reducer,
    <span class="hljs-attr">cartSliceReducer</span>: cartSlice.reducer,
    <span class="hljs-attr">watchlistSliceReducer</span>: watchlist.reducer,
  },
})

<span class="hljs-keyword">export</span> defualt store
</code></pre>
<p>This sets up the store to be consumed an used by multiple components across the application.</p>
<h2 id="heading-how-to-use-redux-states-in-components">How to Use Redux States in Components</h2>
<p>Now that we have our Redux store ready, we can consume and dispatch actions from components using the <code>useSelector</code> and <code>useDispatch</code> hooks.</p>
<p>Here's a simple example:</p>
<pre><code class="lang-js"><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> { cartActions } <span class="hljs-keyword">from</span> <span class="hljs-string">'...'</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">Cart</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">const</span> dispatch = useDispatch()
  <span class="hljs-keyword">const</span> selector = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.watchlistSliceReducer) <span class="hljs-comment">// Since the store has multiple reducers, we need to drill into the appropriate slice state.</span>

  <span class="hljs-keyword">const</span> addToCartHandler = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> dummyitem = {
      <span class="hljs-attr">id</span>: <span class="hljs-built_in">Math</span>.random(),
      <span class="hljs-attr">name</span>: <span class="hljs-string">`Dummy Item <span class="hljs-subst">${<span class="hljs-built_in">Math</span>.random()}</span>`</span>,
      <span class="hljs-attr">price</span>: <span class="hljs-number">20</span> * <span class="hljs-built_in">Math</span>.random(),
    }
    dispatch(cartActions.addItem(cartItem.dummyitem))
  }
  <span class="hljs-keyword">const</span> removeFromCartHandler = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {
    dispatch(cartActions.removeItem(id)) <span class="hljs-comment">//Passing id as an argument to the reducer function.</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {selector.cart.length &amp;&amp;
        selector.cart.map((item) =&gt; {
          return (
            <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>Name: {item.name}<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>Price: {item.price}<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>Quantity: {item.qty}<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">{removeFromCartHandler}</span>&gt;</span>Remove item<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">h3</span>&gt;</span>Total cart value:{selector.cart.total}<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">{addToCartHandler}</span>&gt;</span>Add dummy item<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>
<h2 id="heading-how-to-handle-asynchronous-code-using-action-creators">How to Handle Asynchronous Code Using Action Creators</h2>
<p>So far, so good.</p>
<p>But wait, there's still an important topic we haven't covered – how to handle side effects, or asynchronous code, with Redux. </p>
<p>Consider a scenario where you'd want to dispatch an action that needs to handle a block of code that produces a side effect. But at the same time, reducers should be pure, side effect free, and synchronous.</p>
<p>This means that adding any code in reducers that produce side effects goes against core Redux principles, and is super bad.</p>
<p>To deal with such instances, we have two choices: either using <code>useEffect</code>/ <code>componentDidMount</code>, or by writing action creators.</p>
<h3 id="heading-how-to-handle-side-effects-with-useeffect-or-componentdidmount">How to Handle Side Effects with <code>useEffect</code> or <code>componentDidMount</code></h3>
<p>One way to handle side effect producing code is to use <code>useEffect</code>. By doing this, we split the side effect producing code from the dispatched action itself, so the reducers remain pure and synchronous.</p>
<p>But, one major drawback of using <code>useEffect</code> is code redundancy and duplication.</p>
<p>If there are two or more components that produce the same side effect, we'd want to have the same logic run in those components' <code>useEffect</code> hook, which is a bad practice.</p>
<p>One quick workaround is to put the logic into a helper function and run this function at the root component, and have all the other components listen to the changes via Redux state.</p>
<p>This would be permissible and not necessarily a bad practice, but an even better way would be to use an action creator thunk.</p>
<h2 id="heading-how-to-handle-side-effects-with-action-creators">How to Handle Side Effects with Action Creators</h2>
<p>A thunk is basically a function that returns another function which is not invoked immediately. In fact, we've been using action creators all this time unknowingly when we dispatched action functions.</p>
<p>This is because Redux Toolkit abstracts all this away from us. What's really happening under the hood is that this function returns an action object which corresponds to the appropriate reducer function.</p>
<p>For example, when we do this:</p>
<p><code>dispatch(actions.dispatchActions(args))</code></p>
<p>The method <code>dispatchActions(...)</code> returns an action object with a type and payload property. Roughly speaking, the <code>dispatchActions()</code> function would be something like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dispatchActions</span>(<span class="hljs-params">args</span>) </span>{
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">type</span>: <span class="hljs-string">'UNIQUE'</span>, <span class="hljs-attr">payload</span>: { ...args } }
}
</code></pre>
<p><code>type: 'UNIQUE'</code> is a placeholder, but internally a unique ID is assigned to different action dispatchers, which are then hooked to their respective reducer functions. </p>
<p>So, <code>dispatch(actions.dispatchActions(args))</code> effectively means, <code>dispatch({ type: 'UNIQUE_ID', args: args })</code>. This should also make it clear as to why the <code>payload</code> property is attached on the action dispatcher.</p>
<p>So thunks are like a user defined action creator that returns a function instead of an action object. Action creator thunks are standalone functions, not a reducer function, so we can write asynchronous code there.</p>
<p>An action creator thunk is a function that accepts arguments passed by the user and returns a function that further accepts a dispatch argument passed by Redux Toolkit for us. And it's Redux Toolkit itself that later invokes this returned function.</p>
<p>The boilerplate code of an action creator thunk would look something like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> actionCreatorThunk = <span class="hljs-keyword">async</span>(args) =&gt; {
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">dispatch</span>) =&gt;</span> {
    <span class="hljs-comment">// async code here</span>
    dispatch(actions.actionDispatcher(args))
    <span class="hljs-comment">// more async code</span>
    <span class="hljs-comment">// more dispatch functions</span>
  }
}
</code></pre>
<p>The returned function can also be an <code>async</code> function, because it's clear that it is handling other <code>async</code> code. Action creators can have multiple dispatch functions dispatching multiple dispatch actions.</p>
<p>The action creators thunks can be then dispatched as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> {actionCreatorThunk} <span class="hljs-keyword">from</span> <span class="hljs-string">'...'</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">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Component</span>(<span class="hljs-params">args</span>)</span>{
    <span class="hljs-keyword">const</span> dispatch = useDispatch()

    dispatch(actionCreatorThunk(dataToBePassed))
    ...
    ...
    ...
 }
</code></pre>
<p>The good thing about Redux Toolkit is that it not only accepts action objects returned by action reducer functions, it also accept functions returned by action creators. </p>
<p>When it is identified that a function is returned instead of an action object, Redux Toolkit automatically calls the returned function and passes a dispatch function as an argument.</p>
<p>We can use action creators in places where network calls are made, either to POST or query data from a database, and then set the Redux state from the data sent/received. This ensures the correct coordination between the backend and frontend system.</p>
<h2 id="heading-in-summary">In Summary</h2>
<p>If you've made it thus far, kudos. I really appreciate you taking the time to read until the end.</p>
<p>In a nutshell, synchronous and side effect free code should go into the reducers, while asynchronous code should be used in action creators or side effect handlers such as <code>useEffect</code>.</p>
<p>That's it for this article. I hope this helped you learn something new about writing better Redux code for app-wide state management.</p>
<p>If you have any questions or feedback, feel free to reach out to me on <a target="_blank" href="https://twitter.com/prajwalinbizz">Twitter</a>.</p>
<p>You could also connect with me on <a target="_blank" href="https://linkedin.com/prajwal-kulkarni">LinkedIn</a>.</p>
<p>If you found this article helpful, consider sharing it with your friends who are learning React.</p>
<p>Cheers!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Redux Middleware – What it is and How to Build it from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will explore what middleware is in Redux, why it's used, and how you can create your own middleware from scratch. So let's get started.  What Is Redux Middleware? Redux Middleware allows you to intercept every action sent to the r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-redux-middleware-and-how-to-create-one-from-scratch/</link>
                <guid isPermaLink="false">66bc5535a30f8b3984dad86e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Thu, 09 Sep 2021 16:38:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/redux_middleware.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will explore what middleware is in Redux, why it's used, and how you can create your own middleware from scratch.</p>
<p>So let's get started. </p>
<h2 id="heading-what-is-redux-middleware">What Is Redux Middleware?</h2>
<p>Redux Middleware allows you to intercept every action sent to the reducer so you can make changes to the action or cancel the action.  </p>
<p>Middleware helps you with logging, error reporting, making asynchronous requests, and a whole lot more.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><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> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <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 + action.payload;
    <span class="hljs-keyword">case</span> <span class="hljs-string">"DECREMENT"</span>:
      <span class="hljs-keyword">return</span> state - action.payload;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

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

store.subscribe(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"current state"</span>, store.getState());
});

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">"INCREMENT"</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">1</span>
});

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">"INCREMENT"</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">5</span>
});

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">"DECREMENT"</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">2</span>
});
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/focused-cori-h9iwo">Code Sandbox Demo</a>.</p>
<p>If you want to understand how the above code works in a step-by-step way, check out my <a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners/">Redux for Beginners</a> article.</p>
<p>As I explained in that article, the <code>createStore</code> function accepts three arguments:</p>
<ul>
<li>the first argument is a function that is normally known as a reducer – required argument</li>
<li>the second argument is the initial value of the state – optional argument</li>
<li>the third argument is a middleware – optional argument</li>
</ul>
<h2 id="heading-how-to-create-middleware-in-react">How to Create Middleware in React</h2>
<p>To create a middleware, we first need to import the <code>applyMiddleware</code> function from Redux like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;
</code></pre>
<p>Let's say we're creating a <code>loggerMiddleware</code>. Then to define the middleware we need to use the following syntax:</p>
<pre><code class="lang-js"><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-comment">// your code</span>
};
</code></pre>
<p>The above code is equivalent to the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">store</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">next</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">action</span>) </span>{
      <span class="hljs-comment">// your code</span>
    };
  };
};
</code></pre>
<p>Once the middleware function is created, we pass it to the <code>applyMiddleware</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> middleware = applyMiddleware(loggerMiddleware);
</code></pre>
<p>And finally, we pass the middleware to the <code>createStore</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> store = createStore(reducer, middleware);
</code></pre>
<p>Even though we mentioned above that middleware is the third argument to the <code>createStore</code> function, the second argument (initial state) is optional. So based on the type of arguments, the <code>createStore</code> function automatically identifies that the passed argument is a middleware because it has the specific syntax of nested functions.</p>
<p>Here's an updated <a target="_blank" href="https://codesandbox.io/s/recursing-heyrovsky-q8zl7?file=/src/index.js">Code Sandbox Demo</a> for the above code.</p>
<p>In the above Code sandbox demo, the <code>loggerMiddleware</code> looks like this:</p>
<pre><code class="lang-js"><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">"action"</span>, action);
  next(action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://q8zl7.csb.app/">preview link</a> for the above Code Sandbox demo.  </p>
<p>If you check the console, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/middleware_output.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Before the action is dispatched to the store, the middleware gets executed as we can see the action logged to the console. Because we're calling the <code>next</code> function inside the <code>loggerMiddleware</code> by passing the action, the reducer will also be executed which results in the change in the store.  </p>
<p>Now, what will happen If we don't call the <code>next</code> function inside the <code>loggerMiddleware</code>?  </p>
<p>Then the action will not be sent to the reducer so the store will not be updated.  </p>
<p>If you've worked with Node.js then you might find it similar to how middleware works in Node.js.  </p>
<p>In Node.js middleware also, if we don't call the <em>next</em> function, the request will not be sent forward.</p>
<p>Here's an <a target="_blank" href="https://codesandbox.io/s/dry-dew-6ybfy?file=/src/index.js">updated Code Sandbox Demo</a> with the removed <em>next</em> function call.</p>
<pre><code class="lang-js"><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">"action"</span>, action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://6ybfy.csb.app/">preview link</a> for the above Code Sandbox demo.  </p>
<p>If you check the console, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/middleware_removed_next.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we only get the actions logged to the console. And as the action is not forwarded to the reducer, it will not be executed – so we don't see the <code>console.log</code> from the <code>store.subscribe</code> function.  </p>
<p>As described earlier, we can modify the action from the middleware before it's sent to the reducer.  </p>
<p>Here's an <a target="_blank" href="https://codesandbox.io/s/currying-cherry-nuupf?file=/src/index.js">updated Code Sandbox Demo</a> where we're changing the payload of the action before it's sent to the reducer.</p>
<p>The code for the middleware looks like this:</p>
<pre><code class="lang-js"><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">"action"</span>, action);
  action.payload = <span class="hljs-number">3</span>;
  next(action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://nuupf.csb.app/">preview link</a> for the above Code Sandbox demo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/changed_payload.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As per the code, once the action is logged to the console, we're setting the action payload to a value of 3. So the action <code>type</code> remains the same but the <code>payload</code> is changed.  </p>
<p>So we see the state changed to 3 initially. Then again it's incremented by 3 which makes it 6. Finally it's decremented by 3 making the final state value 3.  </p>
<p>Before the action is sent to the reducer, our <code>loggerMiddleware</code> gets called where we're changing the payload value and we're always setting it to 3 before it's sent to the reducer. So based on the action type INCREMENT or DECREMENT, the reducer will always be changed by a value of 3.  </p>
<p>Even though we're changing the action in the above code, there is no issue in this case because it's a middleware and not a reducer.</p>
<blockquote>
<p>Reducers should be a pure function and we shouldn't make any changes to state and action inside the reducer. You can learn more about it in detail in my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux Course</a>.</p>
</blockquote>
<p>In the above code examples, we've created a single middleware. But you can create multiple middlewares and pass them to the <code>applyMiddleware</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> middleware = applyMiddleware(loggerMiddleware, secondMiddleware, thirdMiddleware);
</code></pre>
<p>All the middlewares mentioned in the <code>applyMiddleware</code> function will be executed one after the another.</p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for reading!</strong></h2>
<p>The content of this article is a small preview from my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>If you want to learn Redux in detail from scratch and build 3 apps along with the <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">complete food ordering app</a>, check out the <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls</li>
<li>Build 3 different apps using Redux</li>
</ul>
<p>and much more.</p>
<p>Finally, we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p><strong>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
