<?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[ Matéu.sh - 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[ Matéu.sh - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:19:55 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/mateush/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is the Virtual DOM in React? ]]>
                </title>
                <description>
                    <![CDATA[ As web applications become more complex, managing updates to the user interface becomes a challenging task. This is where the Virtual DOM (Document Object Model) comes into play – particularly in React, the leading JavaScript library for building use... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-the-virtual-dom-in-react/</link>
                <guid isPermaLink="false">66bc4d2973c9920bb20c0e0c</guid>
                
                    <category>
                        <![CDATA[ DOM ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ virtual dom ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 05 Jun 2024 14:51:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Virtual-DOM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As web applications become more complex, managing updates to the user interface becomes a challenging task. This is where the Virtual DOM (Document Object Model) comes into play – particularly in React, the leading JavaScript library for building user interfaces.</p>
<p>The virtual DOM is a lightweight copy of the real DOM that allows React to manage changes more efficiently by minimizing the direct manipulation required on the real DOM. This process significantly enhances the performance of web apps.</p>
<p>Understanding the virtual DOM is essential for developers who want to get the best out of React. It plays a key role in how React updates the UI, ensuring that changes are applied quickly without unnecessary re-renders.  </p>
<p>In this article, you'll learn:</p>
<ul>
<li>What the virtual DOM is and how it works</li>
<li>How the virtual DOM compares to the real DOM</li>
<li>Benefits of using the virtual DOM</li>
<li>How React uses the virtual DOM</li>
<li>How the virtual DOM compares to the shadow DOM</li>
<li>Common misconceptions about the virtual DOM</li>
</ul>
<h2 id="heading-what-is-the-virtual-dom-and-how-does-it-work">What Is the Virtual DOM and How Does It Work?</h2>
<p>The virtual DOM is an in-memory representation of the real DOM elements. Instead of interacting directly with the real DOM, which can be slow and costly in terms of performance, React creates a virtual representation of the UI components. This virtual representation is a lightweight JavaScript object that mirrors the structure of the real DOM.</p>
<p>Here's a step-by-step process of how the virtual DOM works:</p>
<ol>
<li><strong>Step 1 – Initial Rendering</strong>: when the app starts, the entire UI is represented as a Virtual DOM. React elements are created and rendered into the virtual structure.</li>
<li><strong>Step 2 – State and Props Changes</strong>: as the states and props change in the app, React re-renders the affected components in the virtual DOM. These changes do not immediately impact the real DOM.</li>
<li><strong>Step 3 – Comparison Using Diff Algorithm</strong>: React then uses a <strong>diffing algorithm</strong> to compare the current version of the Virtual DOM with the previous version. This process identifies the differences (or "diffs") between the two versions.</li>
<li><strong>Step 4 – Reconciliation Process</strong>: based on the differences identified, React determines the most efficient way to update the real DOM. Only the parts of the real DOM that need to be updated are changed, rather than re-rendering the entire UI. This selective updating is quick and performant.</li>
<li><strong>Step 5 – Update to the Real DOM</strong>: finally, React applies the necessary changes to the real DOM. This might involve adding, removing, or updating elements based on the differences detected in step 3.</li>
</ol>
<p>For example, let's say we have the following counter functionality in the <code>App</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { 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>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Counter: {count}<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">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>The virtual DOM representation will look like this:</p>
<pre><code class="lang-json">{
 <span class="hljs-attr">"type"</span>: <span class="hljs-string">"div"</span>,
 <span class="hljs-attr">"props"</span>: {},
 <span class="hljs-attr">"children"</span>: [
   {
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"h1"</span>,
     <span class="hljs-attr">"props"</span>: {},
     <span class="hljs-attr">"children"</span>: [
       {
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"TEXT_ELEMENT"</span>,
         <span class="hljs-attr">"props"</span>: {
           <span class="hljs-attr">"nodeValue"</span>: <span class="hljs-string">"Counter: 0"</span>
         }
       }
     ]
   },
   {
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"button"</span>,
     <span class="hljs-attr">"props"</span>: {
       <span class="hljs-attr">"onClick"</span>: <span class="hljs-string">"setCount(count + 1)"</span>
     },
     <span class="hljs-attr">"children"</span>: [
       {
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"TEXT_ELEMENT"</span>,
         <span class="hljs-attr">"props"</span>: {
           <span class="hljs-attr">"nodeValue"</span>: <span class="hljs-string">"Increment"</span>
         }
       }
     ]
   }
 ]
}
</code></pre>
<p>When the <code>Increase</code> button is clicked once, only the <code>h1</code> element is changed:</p>
<pre><code class="lang-json">{
 <span class="hljs-attr">"type"</span>: <span class="hljs-string">"h1"</span>,
 <span class="hljs-attr">"props"</span>: {},
 <span class="hljs-attr">"children"</span>: [
   {
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"TEXT_ELEMENT"</span>,
     <span class="hljs-attr">"props"</span>: {
       <span class="hljs-attr">"nodeValue"</span>: <span class="hljs-string">"Counter: 1"</span>
     }
   }
 ]
}
</code></pre>
<h2 id="heading-comparing-the-virtual-dom-to-the-real-dom">Comparing the Virtual DOM to the Real DOM</h2>
<p>To see the advantages of the virtual DOM, it's important to understand how it differs from the real DOM. The real DOM and the virtual DOM serve similar purposes but operate in distinct ways with significant implications for performance and efficiency.</p>
<p>The real DOM is a built-in standard interface in browsers that represents and interacts with HTML elements, from <code>Doctype</code> declaration and the root <code>html</code> element to every other element in it.</p>
<p>This real DOM represents the whole HTML document as a tree structure and allows JavaScript to manipulate and change HTML documents. Sometimes when those changes occur, the whole document might re-render.</p>
<p>This is in contrast to the virtual DOM, which uses a <strong>diff algorithm</strong> to compare the current and previous versions of updates to the DOM. It only re-renders the parts of the UI that have changed, instead of the whole thing.</p>
<h2 id="heading-benefits-of-using-the-virtual-dom-in-web-development">Benefits of Using the Virtual DOM in Web Development</h2>
<h3 id="heading-simplified-development">Simplified Development</h3>
<p>The Virtual DOM lets you write code in a more declarative style. This means that instead of writing detailed instructions on how to update the UI, you can simply describe what the UI should look like, and React takes care of the rest. This is made possible by React's declarative syntax and its component-based architecture.</p>
<h3 id="heading-improved-performance">Improved Performance</h3>
<p>One of the major advantages of using the virtual DOM is the significant performance improvement it offers. Direct manipulation of the real DOM is slow and can lead to performance issues, especially in complex applications.</p>
<h3 id="heading-enhanced-user-experience">Enhanced User Experience</h3>
<p>The Virtual DOM contributes to a better UX by ensuring that UI updates are smooth, responsive, and without full-page refreshes. Users are less likely to experience lag or jank, resulting in a more seamless interaction with the app.</p>
<h3 id="heading-cross-platform-development">Cross-platform Development</h3>
<p>The principles of the Virtual DOM are not limited to web development only. React Native – a version of React for building cross-platform mobile apps – uses a similar approach. This increases productivity and reduces development time because you can reuse code across web and mobile platforms</p>
<h2 id="heading-common-misconceptions-about-the-virtual-dom">Common Misconceptions About the Virtual DOM</h2>
<p>There are a few misconceptions about the virtual DOM. Let's look at five of these misconceptions and the realities of each of them.</p>
<h3 id="heading-the-virtual-dom-is-a-browser-feature">The Virtual DOM Is a Browser Feature</h3>
<p><strong>Reality</strong>: the virtual DOM is an abstraction implemented by React, not a browser feature. Browsers have the real DOM, which is the standard way to represent and interact with HTML documents. The virtual DOM exists solely in memory within React and is used to optimize updates to the real DOM.</p>
<h3 id="heading-the-virtual-dom-replaces-the-real-dom">The Virtual DOM Replaces the Real DOM</h3>
<p><strong>Reality</strong>: The virtual DOM acts as an intermediary between React and the browser, not a replacement for the real DOM. The real DOM is still what the browser uses to render the UI, but the updates to it are managed through the Virtual DOM.</p>
<h3 id="heading-react-is-the-only-library-and-framework-that-uses-the-virtual-dom">React is the Only Library and Framework that Uses the Virtual DOM</h3>
<p><strong>Reality</strong>: React only popularized the concept of the virtual DOM, it is not the only library or framework that uses it. Other frameworks like VueJS and SolidJS also use the virtual DOM to update the UI.</p>
<h3 id="heading-the-virtual-dom-solves-all-performance-problems">The Virtual DOM Solves All Performance Problems</h3>
<p><strong>Reality</strong>: The virtual DOM can significantly improve performance, but it is not a magical solution to all problems. Poor coding practices, unnecessary renders, and large component trees can still lead to performance issues.</p>
<h3 id="heading-the-virtual-dom-and-shadow-dom-are-the-same">The Virtual DOM and Shadow DOM Are the Same</h3>
<p><strong>Reality</strong>: The virtual DOM and shadow DOM are not the same thing. The virtual DOM is a lightweight copy of the Real DOM with which React optimize UI updates. On the other hand, shadow DOM is a browser technology used to encapsulate the styles and structure of web components.</p>
<h2 id="heading-real-dom-vs-virtual-dom-vs-shadow-dom">Real DOM vs Virtual DOM vs Shadow DOM</h2>
<p>Now that we've established that the virtual DOM, shadow DOM, and real DOM are not the same, let's look at the differences between the three of them.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>Real DOM</strong></td><td><strong>Virtual DOM</strong></td><td><strong>Shadow DOM</strong>  </td></tr>
</thead>
<tbody>
<tr>
<td><strong>Definition</strong></td><td>Standard browser API for representing and interacting with HTML documents</td><td>In-memory representation of the Real DOM</td><td>A browser technology that encapsulates and scopes DOM and style of web components  </td></tr>
<tr>
<td><strong>Flexibility</strong></td><td>Directly manipulated via JavaScript or DOM APIs</td><td>Abstracted and optimized by the framework</td><td>Limited to component boundaries</td></tr>
<tr>
<td><strong>Implementation</strong></td><td>Provided by the browser</td><td>Implemented by frameworks like React and Vue</td><td>Part of the Web Components standard, provided by the browser </td></tr>
<tr>
<td><strong>Performance</strong></td><td>Direct manipulation can be slow and cause performance issues</td><td>Already optimized for efficient updates</td><td>Provides encapsulation, reducing style conflicts </td></tr>
<tr>
<td><strong>Usage</strong></td><td>For rendering and interacting with web documents</td><td>For efficient UI updates by frameworks</td><td>For creating isolated, reusable web components</td></tr>
<tr>
<td><strong>Updates</strong></td><td>Immediate updates to the UI</td><td>Updates are batched and optimized</td><td>Updates are scoped to the component, not affecting the global DOM</td></tr>
<tr>
<td><strong>Repaints</strong></td><td>Frequent updates can cause costly repaints</td><td>Minimizes repaints by batching updates</td><td>Scoped to the component, reducing global repaints</td></tr>
<tr>
<td><strong>Use Cases</strong></td><td>General web development and document manipulation</td><td>Efficient UI updates in frameworks like React and Vue</td><td>Encapsulation of styles and structure in web components</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>As you've read in this article, the Virtual DOM is a key React feature that enhances performance and efficient UI updates. With this, React can batch updates, minimize reflows and repaints, and apply changes efficiently. This makes UI updates fast and smooth, providing a better user experience in the process.</p>
<p>Understanding the Virtual DOM and how it works can help you build performant React applications.</p>
<h2 id="heading-learn-react-and-next-js">Learn React and Next JS</h2>
<p>Want to discover more cool React features like the virtual DOM? Enroll in my React 18 course on Udemy! I'll guide you through the React world by creating a cool 2048 game with animations from scratch.</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-universal"><img src="https://assets.mateu.sh/assets/fcc-universal" alt="Next.js crash course on Udemy" width="600" height="400" loading="lazy"></a>  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Context API Explained with Examples ]]>
                </title>
                <description>
                    <![CDATA[ Managing state has always been a critical aspect of making web applications with React. The most basic way to do this is prop drilling. In prop drilling, you pass props around from the parent component to other components that need it, no matter how ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-context-api-explained-with-examples/</link>
                <guid isPermaLink="false">66bc4d277fa38392bfab8142</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Thu, 30 May 2024 08:13:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Context-API.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Managing state has always been a critical aspect of making web applications with React. The most basic way to do this is prop drilling. In prop drilling, you pass props around from the parent component to other components that need it, no matter how deeply nested they are.</p>
<p>The problem with prop drilling is that, as the application grows in complexity, passing data through multiple levels of components can become messy, cumbersome, and error-prone.</p>
<p>The React Context API was released in 2018 to avoid prop drilling by simplifying state management and making sharing data across the component tree more efficient and error-free.</p>
<p>This article will explore the Context API, starting from understanding the need for it in React applications, to setting it up and using it effectively. We will also look at common use cases, compare it with other state management solutions, and discuss best practices to ensure you use the Context API to its full potential.</p>
<h2 id="heading-understanding-the-need-for-context-in-react">Understanding the Need for Context in React</h2>
<p>Let's look at a basic example in which we have a <code>ParentComponent</code> that holds some <code>count</code> state, and you need to pass that state down to a deeply nested <code>GrandchildComponent</code>.</p>
<p>Here's the <code>ParentComponent</code> that holds the state and <code>setState</code> but not using them:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

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

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Parent Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">small</span>&gt;</span>Not using the count state<span class="hljs-tag">&lt;/<span class="hljs-name">small</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">ChildComponent</span> <span class="hljs-attr">count</span>=<span class="hljs-string">{count}</span> <span class="hljs-attr">setCount</span>=<span class="hljs-string">{setCount}</span> /&gt;</span>
   <span class="hljs-tag">&lt;/&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>This is the <code>ChildComponent</code> that does not use the state and the <code>setState</code> too, but still has to take them from the <code>ParentComponent</code> and pass them to the <code>GrandChildComponent</code> that needs them:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> GrandChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./GrandChildComponent'</span>;

<span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">{ count, setCount }</span>) =&gt;</span> {
 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Child Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">small</span>&gt;</span>Not Using the count state too<span class="hljs-tag">&lt;/<span class="hljs-name">small</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">GrandChildComponent</span> <span class="hljs-attr">count</span>=<span class="hljs-string">{count}</span> <span class="hljs-attr">setCount</span>=<span class="hljs-string">{setCount}</span> /&gt;</span>
   <span class="hljs-tag">&lt;/&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>This is the <code>GrandChildComponent</code> that needs the state and <code>setState</code>, and uses them:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">const</span> GrandChildComponent = <span class="hljs-function">(<span class="hljs-params">{ count, setCount }</span>) =&gt;</span> {
 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Grandchild Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">small</span>&gt;</span>Using the count state<span class="hljs-tag">&lt;/<span class="hljs-name">small</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> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>Count is: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
         <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}
         className="bg-pink-600 p-2 rounded text-white"
       &gt;
         Increase 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> GrandChildComponent;
</code></pre>
<p>And here's what things look like in the browser once the <code>ParentComponent</code> is imported into the <code>Home</code> component of a Next JS project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/prop-drilling.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Prop drilling in React</em></p>
<p>That is prop drilling in action. You can see the <code>ChildComponent</code> that does not use the <code>count</code> state and the <code>setCount</code> still has to absorb both because they'll be used in the <code>GrandChildComponent</code>.</p>
<p>That is how you'll continue to pass the state around in the app. So what if you have components that are still deeper in the tree? Like <code>GreatGrandChild</code> and even <code>GreatGreatGrandChild</code>? Why does a parent have to bother their younger generation with their problems? </p>
<p>In larger applications, prop drilling can make the code harder to maintain and understand. Each intermediary component must be aware of the props it needs to pass down, even if it does not use them.</p>
<p>This is why the Context API exists to prevent this cumbersome prop drilling and make using state in deeply nested components less cumbersome and more straightforward.</p>
<h2 id="heading-how-does-the-context-api-work">How Does the Context API Work?</h2>
<p>The Context API provides a means to share values like state, functions, or any data across the component tree without passing props down manually at every level. This is particularly useful for global data that many components need to access.</p>
<p>To start using the Context API, the first thing you need to do is to create a context using the <code>createContext()</code> method. This function returns a context object with two components – a <code>Provider</code> and a <code>Consumer</code>.</p>
<p>The <code>Provider</code> is used to wrap the part of your component tree where you want the context to be available. It accepts a compulsory <code>value</code> prop that holds the data you want to share across other components. When the <code>value</code> prop of the <code>Provider</code> changes, all descendants that consume the context will re-render.</p>
<p>The <code>Consumer</code> allows any descendant component to use the context. It takes a function as a child, where the function argument is the current context value. In modern React, the <code>useContext</code> hook is often used instead of <code>Consumer</code> for better readability and simplicity.</p>
<h2 id="heading-how-to-set-up-a-context-provider">How to Set Up a Context Provider</h2>
<p>To show you how to set up a context provider, I will use the count state and <code>setCount</code> function from the prop drilling example.</p>
<p>Remember the first thing to do is to create a context using the <code>createContext</code> method. I'll do that in a <code>context/counterContext.js</code> file. This is the convention for naming a context file – <code>functionalityContext.js</code> or <code>.ts</code>. </p>
<p>These are the full steps for setting up a context provider:</p>
<ul>
<li>Import <code>createContext</code> and <code>useState</code> from React </li>
<li>Create a <code>CounterContext</code> constant and set it to <code>createContext</code></li>
<li>Pass in the default values to <code>createContext</code></li>
<li>Create the <code>CounterProvider</code> component that'll take in <code>children</code></li>
<li>Define your <code>state</code> and <code>setState</code></li>
<li>Return a <code>CounterContext.Provider</code> that'll take in the <code>count</code> and <code>setCount</code> as the values of the <code>value</code>  prop</li>
<li>Pass in <code>children</code> – it represents everything to be nested when the Context is consumed</li>
<li>Export <code>CounterContext</code> and <code>CounterProvider</code></li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> CounterContext = createContext({
 <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
 <span class="hljs-attr">setCount</span>: <span class="hljs-function">() =&gt;</span> {},
});

<span class="hljs-keyword">const</span> CounterProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</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">CounterContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">count</span>, <span class="hljs-attr">setCount</span> }}&gt;</span>
     {children}
   <span class="hljs-tag">&lt;/<span class="hljs-name">CounterContext.Provider</span>&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> { CounterContext, CounterProvider };
</code></pre>
<p>This same process applies the same way to any context you want to create.</p>
<h2 id="heading-how-to-consume-context-in-react-components">How to Consume Context in React Components</h2>
<p>To consume a context, the first thing you need to do is to import it and wrap it around the app.</p>
<p>For our small counter app, you can do that inside the <code>layout</code> file of a Next JS 14 project by importing <code>CounterProvider</code> from the <code>counterContext</code> file and wrapping it around <code>{children}</code> inside the <code>body</code> tag:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { CounterProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/context/counterContext'</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">RootLayout</span>(<span class="hljs-params">{
 children,
}: Readonly&lt;{ children: React.ReactNode }&gt;</span>) </span>{
 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{inter.className}</span>&gt;</span>
       {/* Wrap the CounterProvider around the childre */}
       <span class="hljs-tag">&lt;<span class="hljs-name">CounterProvider</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">CounterProvider</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
 );
}
</code></pre>
<p>Now, all pages and components will have access to the <code>count</code> state and <code>setCount</code> function.</p>
<p>Now, inside the <code>GrandChild</code> component where the <code>count</code> state and <code>setCount</code> function are being used, import <code>useContext</code> from <code>'react'</code> and <code>CounterContext</code> from the <code>counterContext</code> file,  then remove the props.</p>
<p>Also, pull out the <code>count</code> state and <code>setCount</code> from the <code>CounterContext</code> you imported like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> { count, setCount } = useContext(CounterContext);
</code></pre>
<p>You can leave the <code>count</code> and <code>setCount</code> as they are and things will work fine:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { CounterContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/context/counterContext'</span>;

<span class="hljs-keyword">const</span> GrandChildComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> { count, setCount } = useContext(CounterContext);

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Grandchild Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">small</span>&gt;</span>Using the count state<span class="hljs-tag">&lt;/<span class="hljs-name">small</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> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>Count is: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
         <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}
         className="bg-pink-600 p-2 rounded text-white"
       &gt;
         Increase 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> GrandChildComponent;
</code></pre>
<p>Everything still works fine:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/prop-drilling-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Context API to mitigate prop drilling in React</em></p>
<h2 id="heading-common-use-cases-for-the-context-api">Common Use Cases for the Context API</h2>
<p>The Context API is versatile and can be used in various scenarios where managing state and sharing data across multiple components is necessary. Here are some common use cases:</p>
<ul>
<li><strong>Global state management in medium to large apps</strong>: the Context API can handle global state management like cart items in an e-commerce app or the currently playing song in a music app.</li>
<li><strong>Authentication management</strong>: using the Context API and other solutions like it to manage the auth state is a common use case for it. States like the current user and auth tokens can be shared across the application using the Context API. This allows any component to access the user authentication status and perform actions like login and logout, or display certain items based on the state.</li>
<li><strong>Theme Management</strong>: Another popular use case for the Context API is theme management (dark mode and light mode toggles). You can do this by storing the theme state in a context, and then accessing and updating the theme in any component without having to pass props through multiple layers.</li>
</ul>
<p>Other use cases are localization, user preferences like notification settings, open, close, and toggle states of a modal, API request management, breadcrumbs navigation, step progress, and any other point where the state is involved. </p>
<h2 id="heading-comparing-context-api-with-other-state-management-solutions">Comparing Context API with Other State Management Solutions</h2>
<p>The Context API is one of several tools available for managing state in a React application. There are others like Redux and Redux Toolkit, Zustand, and MobX. Each of them has its own strengths and ideal use cases.</p>
<h3 id="heading-redux">Redux</h3>
<p>Redux is a third-party library that provides a predictable state container and follows the Flux architecture pattern. It requires more boilerplate code and has a steeper learning curve compared to the Context API.</p>
<p>This steeper learning curve has been significantly lowered by the introduction of Redux Toolkit – a simpler and more lightweight form of Redux.</p>
<p>Redux provides additional features like middleware, time-travel debugging with Redux Devtools, and tools for handling side effects. It is often considered more suitable for larger applications with complex state management needs.</p>
<h3 id="heading-zustand">Zustand</h3>
<p>Zustand is an external library built on the Context API and hooks. It provides a lightweight API for managing global state in React apps by using a single store (or multiple stores when needed). It is more well-suited for small to medium React apps with moderate state management needs.</p>
<p>Zustand automatically handles updates, subscriptions, and efficient re-renders. It supports middleware, DevTools integration, time-travel debugging, and offers features like partial state updates, immutable updates, and selector functions.</p>
<h3 id="heading-mobx">MobX</h3>
<p>MobX is another third-party library that uses observable data and reactions to manage state. It has a more imperative programming style compared to Redux's functional approach. </p>
<p>MobX is easier to learn and use for smaller applications just like the Context API. It provides features like computed values and automatic derivations.</p>
<h2 id="heading-best-practices-for-using-context-api-in-react">Best Practices for Using Context API in React</h2>
<p>If you want to use the Context API effectively, there are a few best practices to follow to ensure your application remains maintainable, performant, and scalable. Here are some guidelines and tips for using the Context API:</p>
<h3 id="heading-always-provide-default-values">Always Provide Default Values</h3>
<p>Providing default values can help you avoid undefined errors when a context is used outside its provider.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserContext = createContext({
 <span class="hljs-attr">user</span>: { <span class="hljs-attr">name</span>: <span class="hljs-string">'Guest'</span>, <span class="hljs-attr">age</span>: <span class="hljs-literal">null</span> },
 <span class="hljs-attr">setUser</span>: <span class="hljs-function">() =&gt;</span> {},
});
</code></pre>
<h3 id="heading-dont-overuse-context">Don't Overuse Context</h3>
<p>Overusing context can lead to performance issues and make state management harder to understand. Only use context for the global state that truly needs to be accessed by many components.</p>
<p>You can do this by creating multiple contexts for different parts of your application instead of a single, all-encompassing context.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ThemeContext = React.createContext();
<span class="hljs-keyword">const</span> AuthContext = React.createContext();
</code></pre>
<p>This reduces unnecessary re-renders and keeps the state management modular.</p>
<h3 id="heading-avoid-frequent-updates">Avoid Frequent Updates</h3>
<p>Use local state for frequently changing data. This is because frequent updates to context values can cause all consuming components to re-render, which might negatively impact performance.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserContext = createContext();

<span class="hljs-keyword">const</span> UserProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'John Doe'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> });
 <span class="hljs-keyword">const</span> [isOnline, setIsOnline] = useState(<span class="hljs-literal">true</span>); <span class="hljs-comment">// local state for a frequently changing data</span>

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">user</span>, <span class="hljs-attr">setUser</span> }}&gt;</span>
     {children}
   <span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>
 );
};
</code></pre>
<h3 id="heading-use-custom-hooks-to-encapsulate-logic">Use Custom Hooks to Encapsulate Logic</h3>
<p>Endeavour to create custom hooks to encapsulate the logic for consuming context. This improves code readability and reusability.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> useUser = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> context = useContext(UserContext);
 <span class="hljs-keyword">if</span> (!context) {
   <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useUser must be used within a UserProvider'</span>);
 }
 <span class="hljs-keyword">return</span> context;
};
</code></pre>
<h3 id="heading-memoize-context-values">Memoize Context Values</h3>
<p>Using the <code>useMemo</code> hook to memoize context values can help prevent unnecessary re-renders of consuming components.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> UserProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> [user, setUser] = useState({ <span class="hljs-attr">name</span>: <span class="hljs-string">'John Doe'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> });

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

 <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">UserContext.Provider</span>&gt;</span></span>;
};
</code></pre>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we explored the Context API, starting with understanding its need and how it works. Using a counter example, we set up a Context Provider and consumed the context in a component to demonstrate its usage.</p>
<p>We discussed common use cases for the Context API and compared it with other state management solutions like Redux, MobX, and Zustand. Finally, we covered best practices for using the Context API effectively. </p>
<p>I hope everything covered in this article helps you get a hang of the Context API and how to use it in your React projects.</p>
<h3 id="heading-learn-react-and-next-js">Learn React and Next JS</h3>
<p>Wanna master more amazing React features like the Context API? Join my React and Next JS course on Udemy! You'll learn how to build the 2048 game from scratch and get insights into solving common mistakes React developers face every day.</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-universal"><img src="https://assets.mateu.sh/assets/fcc-universal" alt="Next.js crash course on Udemy" width="600" height="400" loading="lazy"></a>  </p>
<p>P.S. It would mean the world to me if you decide to share this article on your social media.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Style React Components ]]>
                </title>
                <description>
                    <![CDATA[ You can only make your React app visually appealing to users with styling. That makes styling a fundamental aspect of building captivating user interfaces. With React's component-based architecture, there are a ton of options for styling. These inclu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-style-react-components/</link>
                <guid isPermaLink="false">66bc4d15cd8a65d579e3a962</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 22 May 2024 09:45:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/How-to-style-react-components.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can only make your React app visually appealing to users with styling. That makes styling a fundamental aspect of building captivating user interfaces.</p>
<p>With React's component-based architecture, there are a ton of options for styling. These include traditional CSS, utility-first approach, CSS-in-JS solutions, and more.</p>
<p>In this article, we'll explore various ways to style React components. We'll dive into the best practices for responsive and accessible design, and take a look at performance considerations to guide you in choosing the most effective styling approach for your projects.</p>
<h2 id="heading-how-to-style-react-components-with-inline-styling">How to Style React Components with Inline Styling</h2>
<p>Every JSX element has a <code>style</code> property you can add to its opening tag. This means you can add inline styling to JSX in a React component like in traditional HTML. </p>
<p>The primary difference is that you must specify inline styles as objects. In this object, the keys are the CSS properties written in <em>camelCase</em>, and the values are strings corresponding to valid CSS values.</p>
<p>And because the stylings have to be an object, you have to add them inside two curly braces if you're passing them directly to the element:</p>
<pre><code class="lang-jsx">&lt;h1 style={{ <span class="hljs-attr">textAlign</span>: <span class="hljs-string">'center'</span>, <span class="hljs-attr">marginTop</span>: <span class="hljs-string">'2rem'</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">'#F43596'</span> }}&gt;
  Hello
&lt;/h1&gt;
</code></pre>
<p>You can define the same styles as a separate object and pass it into the <code>style</code> property:</p>
<pre><code class="lang-jsx"><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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> myStyles = {
       <span class="hljs-attr">textAlign</span>: <span class="hljs-string">'center'</span>,
       <span class="hljs-attr">marginTop</span>: <span class="hljs-string">'2rem'</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">'#F43596'</span>,
  };

  <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{myStyles}</span>&gt;</span>Hello<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
       <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>If you want to handle conditional CSS with inline styling in React, you can use a combination of the <code>useState</code> hook and ternary operator:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> ConditionalInlineStyling = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [isActive, setIsActive] = useState(<span class="hljs-literal">false</span>);

 <span class="hljs-keyword">const</span> buttonStyle = {
   <span class="hljs-attr">margin</span>: <span class="hljs-string">'0 auto'</span>,
   <span class="hljs-attr">backgroundColor</span>: isActive ? <span class="hljs-string">'green'</span> : <span class="hljs-string">'gray'</span>,
   <span class="hljs-attr">cursor</span>: isActive ? <span class="hljs-string">'pointer'</span> : <span class="hljs-string">'not-allowed'</span>,
   <span class="hljs-attr">color</span>: <span class="hljs-string">'white'</span>,
   <span class="hljs-attr">padding</span>: <span class="hljs-string">'0.6rem 1.2rem'</span>,
   <span class="hljs-attr">border</span>: <span class="hljs-string">'none'</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">textAlign:</span> '<span class="hljs-attr">center</span>', <span class="hljs-attr">marginTop:</span> '<span class="hljs-attr">2rem</span>' }}&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{buttonStyle}</span>&gt;</span>
       {isActive ? 'Active' : 'Inactive'}
     <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> ConditionalInlineStyling;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/conditional-inline-styling.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conditional inline styling in React</em></p>
<p>The advantage of using inline styling is that it's quick and scoped to an element, while the disadvantage is that it's limited in features, as you cannot directly handle pseudo-classes and pseudo-elements.</p>
<h2 id="heading-how-to-use-css-stylesheets-in-react">How to Use CSS Stylesheets in React</h2>
<p>Using external stylesheets is a common styling approach in React because it's straightforward.</p>
<p>All you need to do is create a CSS file, define your styles in it, and then import the stylesheet into your React component.</p>
<p>But you import the stylesheet using the <code>import</code> keyword and then specify the relative path of the stylesheet, not with the <code>link</code> tag as you do in HTML.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'relative-path-to-css-file.css'</span>
</code></pre>
<p>I have moved the inline styling for the <code>ConditionalInlineStyling</code> component into a separate CSS file and imported it into the page like below:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> <span class="hljs-string">'@/styles/styles.css'</span>; <span class="hljs-comment">// Import the CSS file</span>


<span class="hljs-keyword">const</span> ConditionalStyledComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [isActive, setIsActive] = useState(<span class="hljs-literal">false</span>);

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">button</span> ${<span class="hljs-attr">isActive</span> ? '<span class="hljs-attr">button-active</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">button-inactive</span>'}`}
     &gt;</span>
       {isActive ? 'Active' : 'Inactive'}
     <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> ConditionalStyledComponent;
</code></pre>
<p>Everything still works fine:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/conditional-inline-styling-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conditional styling with CSS file in React</em></p>
<p>The advantage of using traditional stylesheets to style React components is that it's easy to start with, and the only learning curve is how you import it into a component.</p>
<h2 id="heading-how-to-use-css-modules-for-component-specific-styling">How to Use CSS Modules for Component-Specific Styling</h2>
<p>CSS Modules offer a powerful solution for writing component-specific styles in React. They let you scope styles to individual components, thereby letting you avoid naming conflicts and simplifying style maintenance.</p>
<p>If you're using Next JS or any other popular React framework, you don't need any additional steps to start using CSS modules.</p>
<p>To use CSS modules in React, create a file with the <code>.module.css</code> extension. For example, <code>styles.module.css</code>. You then need to import the file into your component with the <code>import</code> keyword and a name you want, for example, <code>styles</code> or <code>classes</code>, followed by the relative path of the CSS modules file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'relative-path-to-css-modules-file.module.css'</span>;
</code></pre>
<p>The name you choose is now an object, the keys are the classes in the CSS modules file and the values are the respective properties in the class.</p>
<p>To use a class from the CSS modules file, you scope the choice import name (<code>style</code> or <code>classes</code>) to a class name. For example <code>&lt;div className={styles.container}&gt;</code>.</p>
<p>I have moved all the styles for the <code>ConditionalInlineStyling</code> component into a CSS modules file I call <code>styles.module.css</code>. Here's how I imported and used it:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'@/styles/styles.module.css'</span>; <span class="hljs-comment">// Import the CSS modules file</span>

<span class="hljs-keyword">const</span> ConditionalStyledComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [isActive, setIsActive] = useState(<span class="hljs-literal">false</span>);


 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.button</span>} ${
         <span class="hljs-attr">isActive</span> ? <span class="hljs-attr">styles.buttonActive</span> <span class="hljs-attr">:</span> <span class="hljs-attr">styles.buttonInactive</span>
       }`}
     &gt;</span>
       {isActive ? 'Active' : 'Inactive'}
     <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> ConditionalStyledComponent;
</code></pre>
<h2 id="heading-tailwind-css-and-utility-first-styling-in-react">Tailwind CSS and Utility-First Styling in React</h2>
<p>Tailwind CSS is a utility-first CSS framework that accelerates styling directly in your markup.</p>
<p>Tailwind does this by offering a comprehensive set of pre-defined utility classes. Instead of writing custom CSS and importing them, you apply the classes to your JSX or HTML elements, minimizing the need for custom CSS.</p>
<p>You can add Tailwind CSS to a Next JS starter by selecting Tailwind in the prompts after running <code>npx create-next-app@latest</code> and everything will be set up for you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-22-at-09.39.45.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>create-next-app</code> CLI tool asking to enable Tailwind CSS</em></p>
<p>Or you can add Tailwind to an existing project by running the commands below:</p>
<pre><code class="lang-bash">$ npm install tailwindcss
$ npx tailwindcss init
</code></pre>
<p>You'll then need to do the configuration yourself, according to your needs. After that, make sure you have the following directives in your <code>globals.css</code> file:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>I have rewritten the <code>ConditionalInlineStyling</code> component to show you what using Tailwind CSS looks like:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> ConditionalStyledComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [isActive, setIsActive] = useState(<span class="hljs-literal">true</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">"text-center mt-8"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">px-4</span> <span class="hljs-attr">py-2</span> ${
         <span class="hljs-attr">isActive</span>
           ? '<span class="hljs-attr">bg-green-600</span> <span class="hljs-attr">text-white</span> <span class="hljs-attr">cursor-pointer</span>'
           <span class="hljs-attr">:</span> '<span class="hljs-attr">bg-gray-500</span> <span class="hljs-attr">text-white</span> <span class="hljs-attr">cursor-not-allowed</span>'
       }`}
     &gt;</span>
       {isActive ? 'Active' : 'Inactive'}
     <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> ConditionalStyledComponent;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/active-inactive-with-tailwind.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conditional styling with Tailwind CSS in React</em></p>
<p>Tailwind CSS is great because it doesn't have a steep learning curve and is the best option for quick prototyping. Other utility-first frameworks are Bootstrap, Bulma, and Chakra UI.</p>
<h2 id="heading-how-to-style-react-apps-with-css-in-js">How to Style React Apps with CSS-in-JS</h2>
<p>CSS-in-JS is a styling approach in which CSS is written in JavaScript, allowing you to style your components using JavaScript syntax.</p>
<p>This method offers a more dynamic and modular way to manage styles, making it easier to handle themes, scoped styles, and both pseudo-classes and pseudo-elements.</p>
<p>styled-components is the most Popular CSS-in-JS library. Others are Emotion and styled-jss.</p>
<p>To use styled-components, you first need to add it to your project by installing it with NPM or any other package manager:</p>
<pre><code class="lang-bash">npm install styled-components
</code></pre>
<p>You then need to import <code>styled</code> from <code>styled-components</code>:</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>
</code></pre>
<p>To define styles for an element or a whole component, you have to define a component and assign it to <code>styled.element-name</code>, then define the styles you want inside the backticks. </p>
<p>For example, the syntax below will create styles for a <code>Button</code> component you can use directly:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> Button = styled.button <span class="hljs-string">`
  /* CSS styles go here */
`</span>;
</code></pre>
<p>Here's how I have rewritten the component to use styled-components:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> styled <span class="hljs-keyword">from</span> <span class="hljs-string">'styled-components'</span>;

<span class="hljs-keyword">const</span> Button = styled.button<span class="hljs-string">`
 background-color: <span class="hljs-subst">${(props) =&gt; (props.isActive ? <span class="hljs-string">'green'</span> : <span class="hljs-string">'gray'</span>)}</span>;
 color: white;
 padding: 0.6rem 1.2rem;
 border: none;
 cursor: <span class="hljs-subst">${(props) =&gt; (props.isActive ? <span class="hljs-string">'pointer'</span> : <span class="hljs-string">'not-allowed'</span>)}</span>;
 transition: background-color 0.3s;
`</span>;

<span class="hljs-keyword">const</span> Container = styled.div<span class="hljs-string">`
 display: flex;
 justify-content: center;
 align-items: center;
`</span>;


<span class="hljs-keyword">const</span> ConditionalStyledComponent = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [isActive, setIsActive] = useState(<span class="hljs-literal">false</span>);

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Container</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">isActive</span>=<span class="hljs-string">{isActive}</span>&gt;</span>
       {isActive ? 'Active' : 'Inactive'}
     <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ConditionalStyledComponent;
</code></pre>
<p>To use pseudo-classes with styled-components, use the <code>&amp;</code> sign to represent the current component, then specify the pseudo-class, for example, <code>:hover</code>.</p>
<p>Here's how I did it:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">'styled-components'</span>;

<span class="hljs-keyword">const</span> Button = styled.button<span class="hljs-string">`
 background-color: green;
 color: white;
 padding: 0.6rem 1.2rem;
 border: none;
 transition: background-color 0.3s;


 &amp;:hover {
   background-color: crimson;
   cursor: pointer;
 }
`</span>;

<span class="hljs-keyword">const</span> Container = styled.div<span class="hljs-string">`
 display: flex;
 justify-content: center;
 align-items: center;
 margin-top: 2rem;
`</span>;

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Hover;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/hover-with-styled-components.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Hover animation using styled-components</em></p>
<h2 id="heading-best-practices-for-responsive-and-accessible-design">Best Practices for Responsive and Accessible Design</h2>
<h3 id="heading-use-responsive-units-everywhere-necessary">Use Responsive Units Everywhere Necessary</h3>
<p>Using responsive units like percentages (<code>%</code>), <code>em</code>, <code>rem</code>, and viewport units (<code>vw</code> and <code>vh</code>) instead of fixed units like px helps your layout adapt fluidly to different screen sizes.</p>
<p><strong>Percentage values</strong> allow elements to scale relative to their container, making it easier to create fluid layouts.</p>
<p><strong>Units like <code>em</code> and <code>rem</code></strong> are based on font size, ensuring that elements scale proportionally to the text size. This is particularly useful for responsive typography, where relative units allow text to scale based on user settings and preferences.</p>
<p><strong>Viewport units (<code>vw</code>  and <code>vh</code>)</strong> are relative to the viewport size, making them ideal for creating elements that scale with the browser window.</p>
<h3 id="heading-use-media-queries-for-responsive-design">Use Media Queries for Responsive Design</h3>
<p>Media queries are foundational to responsive design, as they let you apply different styles based on the device screen size.</p>
<p>By using media queries, you can create breakpoints at specific screen widths and heights to adjust your layout, font sizes, and other styles.</p>
<p>Like traditional CSS, CSS-in-JS libraries like styled-components and Emotion support media queries within their syntax, allowing you to define responsive styles directly in your JavaScript files.</p>
<h3 id="heading-take-advantage-of-flexbox-and-grid">Take Advantage of Flexbox and Grid</h3>
<p>The CSS Grid and Flexbox algorithms revolutionized responsive design. If you're not using them, you're missing out on a cool CSS feature.</p>
<p><strong>CSS Grid</strong> allows you to create complex grid-based layouts that adjust automatically to different screen sizes. This makes it easy to define areas of your layout that should expand or contract. </p>
<p><strong>Flexbox</strong> provides a flexible box model that can rearrange and resize items dynamically.</p>
<p>With CSS grid and Flexbox, you can create responsive navigation bars, form layouts, and other UI components that adjust gracefully as the user resizes the screen.</p>
<h3 id="heading-use-sufficient-color-contrast-for-readability-and-accessibility">Use Sufficient Color Contrast for Readability and Accessibility</h3>
<p>Color contrast between text and background is vital for readability and accessibility. High contrast improves readability and ensures that content is accessible to a wider audience.</p>
<p>Analyzing color contrast visually is not an easy task, that's why there are tools like the <a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAIM Color Contrast Checke</a>r to help you verify that your color choices meet the necessary contrast ratios.</p>
<h2 id="heading-performance-considerations-for-styling-react-components">Performance Considerations for Styling React Components</h2>
<h3 id="heading-avoid-inline-styles-for-large-components">Avoid Inline Styles for Large Components</h3>
<p>The convenience that comes with using inline styles can trick you into using it everywhere.</p>
<p>Excessive inline styles can lead to performance issues because they are recalculated on every render. This potentially causes unnecessary reflows and repaints.</p>
<p>In large components, consider using CSS classes or CSS-in-JS libraries that generate static class names, which are more efficient and easier for the browser to handle.</p>
<h3 id="heading-minimize-and-optimize-css-files">Minimize and Optimize CSS Files</h3>
<p>Because large CSS files can increase the load time of your application, you should consider minimizing your CSS by removing unused styles and compressing the file size.</p>
<p>Tools like <a target="_blank" href="https://cssnano.github.io/cssnano/">CSS Nano</a> and <a target="_blank" href="https://purgecss.com/">PurgeCSS</a> let you compress and minimize CSS files. These tools strip out unnecessary CSS rules, reducing the overall size and improving load times. Additionally, consider splitting your CSS into smaller, component-specific files that can be loaded on demand.</p>
<h3 id="heading-use-css-in-js-with-caution">Use CSS-in-JS with Caution</h3>
<p>When a component renders, CSS-in-JS libraries generate and inject styles, which can become costly if overused. To reduce this, use static styles whenever possible and avoid excessive use of dynamic styles that rely on props or state. Also, consider using the CSS helper or styled function judiciously to keep styles efficient.</p>
<h3 id="heading-use-simple-and-efficient-selectors">Use Simple and Efficient Selectors</h3>
<p>Deeply nested selectors or overly generic selectors can slow down the browser's rendering engine. Aim for simple and efficient selectors that target specific elements or classes. This practice reduces the time the browser spends matching elements to styles.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>React is agnostic of the styling approach you use. That's why it offers a range of styling methods for various needs. Each approach offers unique advantages for creating responsive and accessible designs.</p>
<p>Choosing the appropriate styling method should align with your project requirements and personal preferences. By looking at the strengths of each method, you can develop performant, maintainable, and visually appealing apps that serve a diverse user base across multiple devices.</p>
<h2 id="heading-learn-react-and-next-js">Learn React and Next JS</h2>
<p>Do you want to master React so you can start building real-world applications? Then join my React and Next JS course on Udemy today! I'll teach you React with hands-on coding by building an exciting 2048 game from the ground up, complete with stunning animations!</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-universal"><img src="https://assets.mateu.sh/assets/fcc-universal" alt="Next.js crash course on Udemy" width="600" height="400" loading="lazy"></a> </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Handle Events in React – Explained with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ Event handling is fundamental to understanding how React processes browser events and updates the DOM. As a React developer, it's a critical skill to have, as it enables efficient management of user interactions within web apps.   This article covers... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-handle-events-in-react-19/</link>
                <guid isPermaLink="false">66bc4d0b82b2326c16c01a5d</guid>
                
                    <category>
                        <![CDATA[ events ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Mon, 13 May 2024 09:26:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/React-logo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Event handling is fundamental to understanding how React processes browser events and updates the DOM. As a React developer, it's a critical skill to have, as it enables efficient management of user interactions within web apps.  </p>
<p>This article covers how to set up event handlers and proceeds to more elegant techniques for event management. You'll learn how to create events in React components, pass arguments to the handlers, and prevent default behaviors.  </p>
<p>We'll also cover common event handling patterns and best practices to ensure your applications are performant and easy to maintain.</p>
<h2 id="heading-basic-principles-of-event-handling-in-react">Basic Principles of Event Handling in React</h2>
<p>Event handling in React is guided by a few basic principles that align with its component-based architecture. These principles include:</p>
<ul>
<li>Synthetic event system</li>
<li>Naming conventions</li>
<li>Passing event handlers as props</li>
<li>Inline function and component methods</li>
</ul>
<p>React uses a synthetic event system that ensures events behave consistently across different browsers. This wraps the native event system in browsers, providing a unified API regardless of the browser in which React is run.</p>
<p>Naming conventions revolve around a set of consistent naming that developers use for identifying events and the handler functions at a glance. Every event uses a <code>camelCase</code> naming convention, and the handler function they run is prefixed with "handle", followed by the event name. For example, an <code>onClick</code> event running a <code>handleClick</code> function.</p>
<p>Event handlers are the functions that run when the event is fired. They're usually defined before the render, just above the return statement. On many occasions, they are also passed as <code>props</code> to components. This aligns with React component-based architecture, allowing event logic to be embedded within the components using them.</p>
<p>In React components, events typically run inline functions or standalone functions within the component when fired. With this, you can utilize hooks like <code>useState</code> for state and <code>useCallback</code> for memoizing handler functions. This helps manage state changes and optimize performance.</p>
<h2 id="heading-how-to-create-event-handlers-in-react-components">How to Create Event Handlers in React Components</h2>
<p>Creating an event in React starts with attaching the event name to the element that will fire it, with the handler function referenced in it:</p>
<pre><code class="lang-jsx">&lt;button onClick={handleClick}&gt;
  Click me
&lt;/button&gt;
</code></pre>
<p>What follows is to define that handler function, because it's the function that will run when the event is triggered:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
   alert(<span class="hljs-string">'You clicked me'</span>);
};
</code></pre>
<p>This is the full code that has been imported into the <code>page.jsx</code> file of a Next.js starter:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">const</span> Counter = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
   alert(<span class="hljs-string">'You clicked me!'</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">"p-10 flex items-center"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-green-400 px-4 py-2 rounded mx-auto"</span>
     &gt;</span>
       Click me
     <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>And here's what shows in the browser when the button is clicked:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/onclick-event.png" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js application displaying alert window</em></p>
<p>You can also trigger the event without a separate function. You can do this by defining the function to run as an anonymous function inside the event:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> alert(<span class="hljs-string">'You clicked me!'</span>)}&gt;
  Click me
&lt;/button&gt;
</code></pre>
<p>If you want to update the component state based on an event, you might need the <code>useState</code> hook. Here's an example that shows that using a simple counter application:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> Counter = <span class="hljs-function">() =&gt;</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">"flex items-center justify-center space-x-8 p-10"</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)}
       className="bg-red-500 hover:bg-red-600 text-white font-bold px-4 py-2 rounded "
     &gt;
       Decrement
     <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-4xl font-semibold text-gray-800"</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}
       className="bg-green-500 hover:bg-green-600 text-white font-bold px-4 py-2 rounded "
     &gt;
       Increment
     <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Counter;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/counter-app.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Counter App in Next.js (Animated GIF)</em></p>
<p><code>onChange</code> and <code>onSubmt</code> are other popular events in React. <code>onChange</code> is used on <code>input</code> elements and <code>onSubmit</code> is used on a <code>form</code> element.</p>
<p>Here's an example of an <code>onChange</code> event:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> MyInput = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);

 <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
   setInputValue(e.target.value);
 };

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
       <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span>
       <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">"border border-green-400 p-2 rounded shadow"</span>
       <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type something..."</span>
     /&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-4 text-green-400"</span>&gt;</span>You typed: {inputValue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyInput;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/onchange-event.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Handling input changes in React</em></p>
<p>We'll look at an example of an <code>onSubmit</code> event in the section on how to prevent the default browser behavior when submitting a form.</p>
<p>Other examples of events include keyboard events like <code>onKeyDown</code>, <code>onKeyPress</code>, and <code>onKeyUp</code>,  mouse events like <code>onMouseUp</code>,  <code>onMouseDown</code>, <code>onMouseEnter</code> <code>onDrag</code>, and more. Any popular event in JavaScript is available in React. The only difference is that events are written in <code>camelCase</code> in React.</p>
<h2 id="heading-how-to-pass-arguments-to-event-handlers">How to Pass Arguments to Event Handlers</h2>
<p>Passing arguments to event handlers in React is a common requirement when you need to perform actions on specific data associated with an event. For example, deleting or editing a resource.</p>
<p>To do this, the handler function needs to take in a parameter:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Button click for:'</span>, item);
 };
</code></pre>
<p>You then pass an argument corresponding to that parameter into the anonymous function of the event:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> handleClick(item)}&gt;Click Me&lt;/button&gt;
</code></pre>
<p>Here's an example handling task deletion in a <code>TaskManager</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<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> TaskManager = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [tasks, setTasks] = useState([
   { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Read an article'</span> },
   { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Read a book'</span> },
   { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Write an article'</span> },
   { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'Code'</span> },
 ]);

 <span class="hljs-comment">// Function takes a a taskId parameter</span>
 <span class="hljs-keyword">const</span> deleteTask = <span class="hljs-function">(<span class="hljs-params">taskId</span>) =&gt;</span> {
   setTasks(<span class="hljs-function">(<span class="hljs-params">currentTasks</span>) =&gt;</span>
     currentTasks.filter(<span class="hljs-function">(<span class="hljs-params">task</span>) =&gt;</span> task.id !== taskId)
   );
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Deleted task with ID:'</span>, taskId);
 };

 <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">"p-5 max-w-md mx-auto bg-gray-100 rounded-lg shadow"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"list-none space-y-2"</span>&gt;</span>
       {tasks.map((task) =&gt; (
         <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
           <span class="hljs-attr">key</span>=<span class="hljs-string">{task.id}</span>
           <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-between items-center bg-white p-3 rounded shadow-sm"</span>
         &gt;</span>
           {task.text}
           <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
             // <span class="hljs-attr">onClick</span> <span class="hljs-attr">event</span> <span class="hljs-attr">takes</span> <span class="hljs-attr">a</span> <span class="hljs-attr">task.id</span> <span class="hljs-attr">argument</span> <span class="hljs-attr">to</span> <span class="hljs-attr">account</span> <span class="hljs-attr">for</span> <span class="hljs-attr">the</span> <span class="hljs-attr">taskId</span> <span class="hljs-attr">parameter</span> <span class="hljs-attr">of</span> <span class="hljs-attr">the</span> <span class="hljs-attr">function</span>
             <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> deleteTask(task.id)}
             className="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-3 rounded"
           &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>
 );
};


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TaskManager;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/task-deletion.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Item delete is a great example of parametrized event handler</em></p>
<h2 id="heading-common-event-handling-patterns-in-react">Common Event Handling Patterns in React</h2>
<p>Event handling patterns refer to the techniques for handling user interactions within React components.</p>
<p>These patterns include but aren't limited to:</p>
<ul>
<li>Binding event handlers with <code>useCallback</code> to memoize the handler</li>
<li>Event handlers with parameters (you've seen this in the section on how to pass arguments to event handlers)</li>
<li>Conditional event handling</li>
<li>Event delegation</li>
<li>Event bubbling</li>
<li>Optimized handling for lists</li>
<li>Inline arrow functions (anonymous functions that you pass into event handlers)</li>
</ul>
<p>Here's an example using <code>useCallback</code> to prevent creating a new function on every render:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useCallback } <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">HandlerComponent</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">const</span> handleClick = useCallback(<span class="hljs-function">() =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Button clicked'</span>);
 }, []);

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>
     Click Me
   <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
 );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> HandlerComponent;
</code></pre>
<p>And here's an example of conditional event handling:</p>
<pre><code class="lang-jsx"><span class="hljs-string">'use client'</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">CheckLogin</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">const</span> [isLoggedIn, setLoggedIn] = useState(<span class="hljs-literal">false</span>);

 <span class="hljs-keyword">const</span> toggleLogin = <span class="hljs-function">() =&gt;</span> {
   setLoggedIn(!isLoggedIn);
 };

 <span class="hljs-keyword">const</span> handleLogin = <span class="hljs-function">() =&gt;</span> {
   <span class="hljs-keyword">if</span> (isLoggedIn) {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User is logged in'</span>);
   } <span class="hljs-keyword">else</span> {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User is logged out'</span>);
   }
 };

 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl text-center mb-4"</span>&gt;</span>
       {isLoggedIn ? 'User is logged in' : 'User is not logged in'}
     <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">{handleLogin}</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-green-400 hover:bg-green-500 px-2 py-3 rounded mr-3"</span>
     &gt;</span>
       Check Login
     <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">{toggleLogin}</span>
       <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-green-400 hover:bg-green-500 px-2 py-3 rounded"</span>
     &gt;</span>
       {isLoggedIn ? 'Log Out' : 'Log In'}
     <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> CheckLogin;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/conditional-event.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app checks if user is logged-in</em></p>
<h2 id="heading-how-to-prevent-the-default-browser-behavior-in-event-handlers">How to Prevent the Default Browser Behavior in Event Handlers</h2>
<p>Default browser behavior is the automatic actions the browser performs when a specific event is fired. In event handling, the most common default browser behavior is that it refreshes when a form is submitted. </p>
<p>To prevent the browser from refreshing when a form is submitted, or prevent any other default behavior, pass the <code>event</code> parameter into the function handling the <code>onSubmit</code> event, then use that <code>event</code> to call a <code>preventDefault</code> function.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
 <span class="hljs-comment">// prevent the default behavior</span>
 event.preventDefault();
};

<span class="hljs-keyword">return</span> (
 <span class="hljs-comment">// reference the function in onSubmit</span>
 <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
     <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
     <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span>
     <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</span>
     <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter something..."</span>
   /&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
);
</code></pre>
<h2 id="heading-best-practices-for-efficient-event-handling-in-react">Best Practices for Efficient Event Handling in React</h2>
<p>Here are the most important rules for event handling in React:</p>
<h3 id="heading-avoid-using-anonymous-arrow-functions-inside-events">Avoid Using Anonymous Arrow Functions Inside Events</h3>
<p>It looks convenient to use arrow functions directly in events, like <code>onClick={() =&gt; console.log('button clicked')})</code>. The downside to this is that it can lead to performance issues because a new function is created on every render.</p>
<p>Always define the handler function to run when the event is fired outside the render method to avoid those performance issues.</p>
<h3 id="heading-memoize-events-with-usecallback-hook">Memoize Events with useCallback hook</h3>
<p>For components that re-render often, memoizing the handlers in it with the <code>useCallback</code> hook can prevent unnecessary re-renders. This is useful when passing events as props to child components that might re-render unnecessarily.</p>
<h3 id="heading-use-event-delegation">Use Event Delegation</h3>
<p>For multiple similar elements, like items in a list, consider using event delegation. Attach a single event listener to the parent element and use the event target to handle user interaction with child elements. This reduces the number of event listeners and can improve performance.</p>
<h3 id="heading-prevent-default-behavior-where-necessary">Prevent Default Behavior Where Necessary</h3>
<p>Use <code>event.preventDefault()</code> in your event handlers when you need to stop the browser from performing default actions, like submitting a form. However, you should use this method prudently to avoid blocking browser behaviors unnecessarily.</p>
<h3 id="heading-clean-up-event-listeners">Clean Up Event Listeners</h3>
<p>If you set up your event listeners in <code>useEffect</code>, always return a cleanup function to remove the event listener. Otherwise, it'll cause memory leaks.</p>
<h3 id="heading-test-event-handlers">Test Event Handlers</h3>
<p>Make sure your event handlers are covered in your unit and integration tests. Testing frameworks like Jest combined with React Testing Library can help verify that your event handlers are functioning as expected.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned the fundamentals of event handling in React, focusing on how to use the React synthetic event system to create events in React web apps.</p>
<p>We explored defining event handlers, passing arguments, and preventing default browser behaviors to enhance user experiences.</p>
<p>In addition, you learned about the benefits of using <code>useCallback</code> to optimize event handlers for efficient performance under various user interactions.</p>
<p>With these insights, you should be able to implement event handling in your projects, so you can improve both functionality and user engagement.</p>
<h2 id="heading-bring-your-react-skills-to-the-next-level">Bring your React skills to the next level</h2>
<p>Would you like to learn more about event handling or other React concepts? Then join my React course on Udemy. I will show you how to become a better React developer by building a 2048 Game. Building games make learning more fun and enjoyable.</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-events-in-react"><img src="https://assets.mateu.sh/assets/fcc-events-in-react" alt="Next.js crash course on Udemy" width="600" height="400" loading="lazy"></a></p>
<p> So join now and start your journey to mastering React!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use React Developer Tools – Explained With Examples ]]>
                </title>
                <description>
                    <![CDATA[ Traditional browser developer tools are designed to inspect and debug web pages by interacting with your HTML, CSS, and JavaScript code. However, you can't use them to inspect and debug React applications efficiently due to the nature of React. This ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-react-devtools/</link>
                <guid isPermaLink="false">66bc4d2460ad5c1520c1668f</guid>
                
                    <category>
                        <![CDATA[ devtools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Mon, 06 May 2024 20:12:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/React-Devtools.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Traditional browser developer tools are designed to inspect and debug web pages by interacting with your HTML, CSS, and JavaScript code. However, you can't use them to inspect and debug React applications efficiently due to the nature of React.</p>
<p>This is where the React Developer Tools, AKA React DevTools comes into play. It allows you to inspect and debug your React applications by providing access to the components, states, hooks, props, what renders what, and more.</p>
<p>This article will show you how to use React DevTools by focusing on components, props, and state inspection. We'll also examine how to use it to enhance application performance.</p>
<p>For demonstration, we'll use the 2048 game code. You can grab it in <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react">this GitHub repository</a>.</p>
<h2 id="heading-how-to-install-react-developer-tools">How to Install React Developer Tools</h2>
<p>Installing the React developer tools extension for your browser is the most common way to use it. </p>
<p>If you use Chrome, visit the Chrome Webstore and search for "React", then select "React Developer Tools" and click the "<em>Add to Chrome</em>" button to install it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-11.14.42.png" alt="Image" width="600" height="400" loading="lazy">
<em>React Devtools in Chrome Web Store</em></p>
<p>React DevTools is also available as a standalone electron app, an NPM package, and an add-on for both Edge and Firefox browsers. If you use the Safari browser, consider using the NPM package.</p>
<p>If you use the extension on Chrome but want to migrate your data to either Edge and Firefox, it will be automatically installed for you!</p>
<h2 id="heading-how-to-navigate-the-react-developer-tools-interface">How to Navigate the React Developer Tools Interface</h2>
<p>After installing the DevTools as an extension, open your browser console and you should see two additional tabs – Components and Profiler.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Chrome with React DevTools extension</em></p>
<p>The Components tab displays a tree view of the components in your application. It also gives you access to the hooks and props in each component.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-11.22.31.png" alt="Image" width="600" height="400" loading="lazy">
<em>Components tab in React DevTools</em></p>
<p>The Profiler tab allows you to analyze the runtime performance of your applications and identify costly re-renders or performance bottlenecks. From there, you can import and export recorded performance sections and see how long a component renders or why it re-renders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-11.23.32.png" alt="Image" width="600" height="400" loading="lazy">
<em>Profiler tab in React DevTools</em></p>
<p>If you click the gear icon on the right side in any of the tabs, you should see a pop-up with 4 tabs – General, Debugging, Components, and Profiler.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-11.24.24.png" alt="Image" width="600" height="400" loading="lazy">
<em>React DevTools settings</em></p>
<p>In the 4 tabs, you can adjust settings related to theme, display, debugging options, component filters, and recording settings for the profiler.</p>
<h2 id="heading-how-to-inspect-react-components-with-devtools">How to Inspect React Components with DevTools</h2>
<p>In the Components tab, you can select a component and inspect it, just like you'd do with HTML elements in a traditional browser's dev tools.</p>
<p>To do that, click the select icon on the top-left corner, then select any part of the app to see the component that represents it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-1--1-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Inspecting components in React DevTools</em></p>
<p>As you make changes that involve adding something, new components will be added to the tree.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-2.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Live component updates in React DevTools</em></p>
<p>On the right-hand side in the Components tab are the <code>props</code>, <code>hooks</code>, <code>renderer</code>, and the <code>source</code> for any component you select in the tree.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Component details in React DevTools</em></p>
<h2 id="heading-how-to-explore-component-state-and-props">How to Explore Component State and Props</h2>
<p>Remember that when you select a component in the tree, the state and props in that component are available on the right-hand side.</p>
<p>In the screenshot below, I have selected a <code>Tile</code> component for you to see the props:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tile component selected</em></p>
<p>You can see that the <code>Tile</code> component has <code>id</code>, <code>position</code>, and <code>value</code> properties. From here, you can add a new prop and edit the existing props.</p>
<p>For example, I just changed a <code>value</code> prop from <code>2</code> to <code>4</code> and it reflected in the UI in real-time:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-3.gif" alt="Image" width="600" height="400" loading="lazy">
<em>change value from 2 to 4</em></p>
<p>You can also make changes to a piece of state. For instance, the scorecard you can see in the UI is a piece of state in the <code>GameProvider</code> context. It updates your score as you play the game.</p>
<p>You can select the <code>GameProvider</code> context, look for the <code>score</code> state, and change it to something else:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-4.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Change score state</em></p>
<h2 id="heading-how-to-debug-react-applications-with-react-devtools">How to Debug React Applications with React DevTools</h2>
<p>The traditional browser developer tools is good for debugging your HTML, CSS, and JavaScript code, but it has limitations concerning debugging React applications.</p>
<p>This is the primary reason React DevTools was created in the first place, as it has the essential built-in features that can show you everything you need to debug your React apps.</p>
<p>One of the errors the browser can help you debug is a reference error. For instance, if there's an error in any of your components, the browser can show you the error message and the line affected.</p>
<p>For example, I've forced an error by changing <code>cells</code> to <code>cell</code> on line 62 in the <strong>board.tsx</strong> file of the app. This is what the error message looks like in the browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-12.08.50.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reference Error in React 19</em></p>
<p>You can then go to the line of code where the error occurred and make the necessary adjustments so the app can run again.</p>
<p>React DevTools also shows you a reference error and the component in which it occurs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-12.11.19.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reference Error in React DevTools</em></p>
<h2 id="heading-how-react-devtools-takes-debugging-to-the-next-level">How React DevTools Takes Debugging to the Next Level</h2>
<p>In the Components tab, above the items on the right-hand side, are iconized buttons you can use to:</p>
<ul>
<li>Force the selected component to an errored state </li>
<li>Inspect the matching DOM element</li>
<li>Suspend the selected component</li>
<li>Log the component data to the console</li>
<li>View the source code for the elements in the selected component</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>Component utilities in React DevtTools</em></p>
<p>For example, if the tiles in the game are not showing as they should, it's probably a styling issue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-12.16.43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Unstyled tiles in 2048 Game</em></p>
<p>This particular error will not stop your app from running, so the best way to debug it is to use React DevTools instead of looking through your code, especially if it's large.</p>
<p>You can select the <code>Tile</code> component and log its data to the console. When you do this, the <code>props</code>, <code>hooks</code>, and <code>nodes</code> of that component will be logged for you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Utility allowing to log component data to the console in React DevTools</em></p>
<p>To see the component's data, you have to switch to the console tab and inspect the <code>nodes</code> to see what might have gone wrong.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-12.21.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>Component data printed in the console React DevTools</em></p>
<p>In the image above,it shows that there is a <code>div</code> element with an undefined <code>className</code>. This tells you that you've misspelt a <code>className</code> value, so you need to go back to your code and correct it.</p>
<p>If the error you're getting has to do with <code>props</code> or <code>hooks</code>, then you need to open up any of them to see what went wrong.</p>
<p>You can also look through the source code of any component causing an issue. For instance, if the scoreboard is not showing as it has to, select the component and click the "View source code for this element" icon.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>View source of this component utility in React DevTools</em></p>
<p>After the source code is displayed, you can step through the end of each line. Any line end that is red when you do that is the one causing the error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-5.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can then go back to your editor and make the necessary changes on that line.</p>
<h2 id="heading-performance-analysis-with-react-devtools">Performance Analysis with React DevTools</h2>
<p>Doing performance analysis with React can help you understand the efficiency of your application and identify any performance bottlenecks. This is what the Profiler tab lets you do.</p>
<p>To do this, switch to the Profiler tab and click the "Start profiling" icon to start recording.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-31.png" alt="Image" width="600" height="400" loading="lazy">
<em>Record button in the Profile tab of React DevTools</em></p>
<p>Perform the actions in your app you want to analyze. This could be page loads, user interactions like button clicks, swiping, or dynamic content loading. When you're done, click "Stop" to end the recording.</p>
<p>The Profiler will then display a flame graph and a list of commits. Each commit represents a render phase of your React application. Components that take longer to render will have wider bars.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/devtools-6.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can then select a specific commit to view detailed information about the render performance of components during that commit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-06-at-12.28.57-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Profiling results in React DevTools</em></p>
<p>You can also download the profiling session, or import a profiling session. This means you can share the session with your teammates.</p>
<h2 id="heading-common-issue-and-solution-how-to-fix-react-devtools-not-showing">Common Issue and Solution: How to Fix React DevTools Not Showing</h2>
<p>If DevTools fails to show up, it could be because it doesn't have access to the React sites you're viewing in the browser.</p>
<p>To fix this, type <code>chrome://extensions/</code> into the address bar and hit enter, then search for the extension and make sure it's toggled on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to enable React DevTools extension in Google Chrome</em></p>
<p>If that doesn't fix the issue, click the "Details" button and make sure you grant an "On all sites" access under the "Site access" option</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Group-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to change extension's site access settings in Google Chrome</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>From inspecting the component hierarchy and modifying state and props to profiling performance and understanding complex re-renders, React Developer Tools offers a comprehensive set of features that can improve the quality of your React applications.</p>
<p>Whether you're a beginner aiming to have a better understanding of the inner workings of React, or an experienced developer looking to optimize your applications, investing the time to master React Developer Tools will be profitable in your development processes.</p>
<h2 id="heading-learn-react-and-next-js">Learn React and Next JS</h2>
<p>Are you ready to dive deep into React and start creating real-world applications? Enroll in my <a target="_blank" href="https://assets.mateu.sh/r/fcc-react-devtools">React and Next JS course on Udemy</a>! You'll learn through hands-on coding as we build an incredible 2048 game from scratch with cool animations.</p>
<p>Join now and start your journey to becoming an employable React developer!</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-react-devtools"><img src="https://assets.mateu.sh/assets/fcc-react-devtools" alt="Learn Next.js and React 19 to Create 2048 Game From Scratch" width="600" height="400" loading="lazy"></a><br><em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How To Use CSS Variables – Explained with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ If you are building websites or web apps, you should already know that code repetition is considered a bad practice. That's why you should learn how to use CSS variables to reduce the amount of CSS code you write and take your styling to a new level.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-css-variables/</link>
                <guid isPermaLink="false">66bc4d1860ad5c1520c1668d</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ variables ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Tue, 02 Apr 2024 19:53:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/CSS-Variables.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are building websites or web apps, you should already know that code repetition is considered a bad practice.</p>
<p>That's why you should learn how to use CSS variables to reduce the amount of CSS code you write and take your styling to a new level.</p>
<p>The most successful web apps have spectacular designs. Unfortunately, to reach the desired effects, web developers need to prepare large amounts of styles. This forces us to repeat values, such as colors, in many different elements. </p>
<p>Fortunately, modern stylesheets support CSS variables, which lets you reduce repetition in your codebase. You don't need external tools such CSS modules, Less or SASS to take advantage of it. </p>
<p>In this comprehensive guide, I'm going to show you how to effectively use CSS variables, covering basic examples in plain HTML and CSS to more advanced frameworks like React and Next.js.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This guide is dedicated to beginners so you don't need any special knowledge to benefit from it. </p>
<p>I included a few examples in React and Next.js and they are dedicated to beginner React developers. Only those examples will require basic React knowledge to understand them. Feel free to skip them if you don't work with React.</p>
<h2 id="heading-what-are-css-variables">What are CSS Variables?</h2>
<p>CSS variables (officially called CSS custom properties) allow developers to manage and reuse values in CSS stylesheets. Web developers can define reusable variables that can use be used across many CSS files, making code easier to update. CSS variables make it super easy to implement features such as dark mode.</p>
<p>Modern websites require large amounts of styles and this results in repeated CSS values in many different stylesheets. The ecosystem was working hard to address this issue by inventing tools such as SASS, Less and CSS modules but all of those tools have a flaw – they need to be compiled to CSS files in the end.</p>
<p>Fortunately, thanks to CSS variables, we can simplify our stylesheets without sophisticated tools and build processes.</p>
<h2 id="heading-how-to-create-css-variables">How To Create CSS Variables</h2>
<p>Defining a CSS variable is quite simple. You can define a CSS variable using the <code>--</code> prefix followed by a name of your choice, then assigning it a value using the <code>var()</code> function. </p>
<p>Here's how you do it:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-comment">/* Backgrounds */</span>
  <span class="hljs-attribute">--primary-background</span>: <span class="hljs-number">#faf8ef</span>;
  <span class="hljs-comment">/* Colors */</span>
  <span class="hljs-attribute">--primary-text-color</span>: <span class="hljs-number">#776e65</span>;
}
</code></pre>
<p>As you can see, I defined CSS variables inside the <code>:root</code> pseudo-class to make them globally available. </p>
<p>Each variable started with <code>--</code>, followed by a name: <code>--primary-background</code> or <code>--primary-text-color</code>. Lastly, I assigned values to those variables.</p>
<p>Using this, I'll be able to change website colors just by modifying the values of those variables.</p>
<h2 id="heading-how-to-use-css-variables">How To Use CSS Variables</h2>
<p>Now let me show you how to use CSS variables to define global background and text color for your website:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--primary-background);
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--primary-text-color);
}
</code></pre>
<p>To use a variable, you need to refer to them by using the <code>var()</code> function and passing the variable name as an argument.</p>
<p>That's it! Now your website is using CSS variables to render styles.</p>
<p><strong>Note</strong>: <code>var()</code> helper is a built-in CSS function so you don't need any libraries to use it.</p>
<h2 id="heading-how-to-use-css-variables-in-react">How To Use CSS Variables in React?</h2>
<p>Many web developers build their web apps in React so I will show you how you can get values and update CSS variables in React. Many modern web apps support dark mode and this feature can become one of a React developer's nightmares. </p>
<p>Next, I'll show you an easy method to add a dark mode in React apps just by using CSS variables. </p>
<h3 id="heading-how-to-set-the-value-of-css-variable-in-react">How To Set the Value of CSS Variable in React?</h3>
<p>Changing the value of CSS variables in React might be tricky since React doesn't offer any tools to directly interact with the DOM tree. That's why we'll use plain JavaScript to read and set CSS variables. </p>
<p>Here's how you can set a CSS Variable in React:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Example</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.documentElement.style.setProperty(<span class="hljs-string">'--primary-background'</span>, <span class="hljs-string">`black`</span>);
    <span class="hljs-built_in">document</span>.documentElement.style.setProperty(<span class="hljs-string">'--primary-text-color'</span>, <span class="hljs-string">`white`</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">{{color:</span> "<span class="hljs-attr">var</span>(<span class="hljs-attr">--primary-text-color</span>"}}&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
};
</code></pre>
<p>As you can see, I took advantage of the global <code>document</code> variable to get into the DOM tree and modify style properties. I used <code>setProperty</code> method that requires two arguments:</p>
<ul>
<li>CSS custom property (CSS variable) name.</li>
<li>The value of the variable.</li>
</ul>
<p><strong>Note</strong>: It doesn't matter if you work in React or plain JavaScript, you can always call <code>document.documentElement.style.setProperty</code> to modify CSS variable values. It's a JavaScript built-in function.</p>
<h3 id="heading-how-to-get-the-value-of-css-variables-in-react">How To Get the Value of CSS Variables in React?</h3>
<p>Sometimes you might need to read the value of a CSS variable and store it in React. In this case, I would suggest utilizing <code>useState</code> and <code>useEffect</code> hooks. </p>
<p>Here's how I would approach this issue:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useEffect, setState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Example</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [color, setColor] = useState(<span class="hljs-string">'black'</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> cssColor = <span class="hljs-built_in">document</span>.documentElement.style.getPropertyValue(<span class="hljs-string">'--primary-text-color'</span>);
    setColor(cssColor);
  }, [])

  <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">{{color:</span> <span class="hljs-attr">color</span>}}&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
};
</code></pre>
<p>As you can see, I retrieved the value of a <code>--primary-text-color</code> variable to the <code>cssColor</code> constant. In the next line, I updated component's state by using <code>setColor</code> helper created by <code>useState</code> hook. Using the method, my CSS variable can be used easily in React Components.</p>
<p>That's it. Now you can use this variable in your React app.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>CSS variables can be used in different kinds of websites and no JavaScript is needed to take advantage of them. Everybody can benefit of them – no matter their level of experience in web development. Understanding CSS variables can greatly improve your styling experience and make you more efficient.</p>
<p>I hope you liked this article. It would mean the world to me if you share it on your social media.</p>
<p>If you have any questions or just want to hear updates from me, you can find me on <a target="_blank" href="https://twitter.com/msokola">Twitter</a>.</p>
<h2 id="heading-learn-react">Learn React</h2>
<p>If you are still learning React or you want to learn more tricks like this one, you should join my course on Next.js. Next.js is the most popular React framework that powers the most of React app these days. I will teach you how to use it by building an awesome 2048 game with animations. No fluff. Tactics only.</p>
<p>🚀 <strong>Join m</strong>y <a target="_blank" href="https://www.mateu.sh/learn-nextjs">Next.js Crash <strong>Course</strong></a>.</p>
<p>This course includes:</p>
<ul>
<li>🎥 5.5 hours on-demand video</li>
<li>📱 Access on mobile and TV</li>
<li>🗓️ Full lifetime access</li>
<li>🎓 Certificate of completion</li>
</ul>
<p><a target="_blank" href="https://mateu.sh/learn-nextjs"><img src="https://assets.mateu.sh/assets/fcc-css-variables" alt="Click to join the Next.js Crash Course" width="600" height="400" loading="lazy"></a><br><em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How To Use Prettier in Visual Studio Code ]]>
                </title>
                <description>
                    <![CDATA[ Nowadays, every tech company strives to build quality software fast. That's why every developer must learn how to write clean and readable code.  But when a project is managed by multiple developers, the focus shifts into consistency especially in te... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-prettier-in-visual-studio-code/</link>
                <guid isPermaLink="false">66bc4d219212975c61bba79c</guid>
                
                    <category>
                        <![CDATA[ Prettier ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Mon, 18 Mar 2024 12:35:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/Prettier.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Nowadays, every tech company strives to build quality software fast. That's why every developer must learn how to write clean and readable code. </p>
<p>But when a project is managed by multiple developers, the focus shifts into consistency especially in terms of written code. </p>
<p>Keeping a consistent code style and formatting across many team members and project is a challenging task. It's almost impossible to do it manually, but that's where Prettier comes into play.</p>
<p>In this guide, you will learn how to install Prettier in Visual Studio Code and how to use it to format code.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you follow this guide, you will need to download and install <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>.</p>
<h2 id="heading-what-is-prettier">What is Prettier?</h2>
<p>Prettier is a powerful code formatter that automates this process from start to finish. It gives you confidence that your code adheres to defined coding standards without any manual actions (unless you want to have it manual).   </p>
<p>Prettier not only supports all JavaScript libraries and frameworks, such as Angular, React, Vue, and Svelte, but also works with TypeScript.</p>
<p>That's why it is used by many people in tech worldwide.</p>
<h2 id="heading-how-to-install-prettier-in-visual-studio-code">How To Install Prettier in Visual Studio Code</h2>
<p>To install Prettier in Visual Studio Code, you need to:</p>
<ol>
<li>Open the Extensions tab.</li>
<li>Type prettier in the search box.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---1--2-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Extensions</em></p>
<p>At the top of the list you will find the Prettier - Code formatter extension. You need to open it, and click the Install button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Extensions / Prettier - Code Formatter</em></p>
<p>After the successful installation you will see the text saying "This extension is enabled globally"<em>:</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---2--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Extensions / Prettier - Code Formatter (Installation completed)</em></p>
<h2 id="heading-how-to-activate-prettier-in-visual-studio-code">How To Activate Prettier in Visual Studio Code</h2>
<p>When your Prettier extension is installed, you need to configure Visual Studio Code to take advantage of it. You can do in the Settings tab. </p>
<p>Side node: to open the Settings tab, you can use <code>COMMAND + ,</code> on macOS or <code>CTRL + ,</code> on Windows and Linux:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Main view</em></p>
<p>At the top of the Settings tab you will find a search box. Now, you need to type formatter, and then Editor: Default Formatter will pop up on the settings list:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Settings</em></p>
<p>Now, open the dropdown and select Prettier - Code formatter from the list:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Settings / Default Formatter</em></p>
<p>Now, Prettier is your default code formatter, but you might want to enable Visual Studio Code to automatically format code when you save files. </p>
<p>If you want to, just tick the checkbox in the Format On Save section:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---7.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Settings / Format On Save</em></p>
<h2 id="heading-how-to-format-code-with-prettier-in-visual-studio-code">How To Format Code with Prettier in Visual Studio Code</h2>
<p>Let's take a look at one React component I created: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---8--2-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Unformatted React 18 Component</em></p>
<p>As you can see, this code is completely misaligned, it misses semicolons, and it is very difficult to read. The code could formatted in a better way, right? Here's where Prettier comes into play.  </p>
<p>To format code, we need to open the command palette – you can use <code>COMMAND + SHIFT + P</code> on macOS or <code>CTRL + SHIFT + P</code> on Windows and Linux. </p>
<p>Now, you need to find Format Document. Feel free to use the search box:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Format Document command</em></p>
<p>After running Format Document your code becomes neat and clean:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Prettier---10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code / Formatted React 18 Component (with Prettier)</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Integrating Prettier into Visual Studio Code is a game-changer for developers striving to maintain a consistent and high-quality codebase. </p>
<p>By automating the formatting process, you are not only adhering to coding standards but are also reducing the struggle that comes with manual code formatting. That's why every developer should use Prettier to ensure consistency in their codebase. </p>
<p>I hope this article helped you a lot. It'd mean the world to me if you shared it on your social media.</p>
<p>If you have any questions you can reach me on <a target="_blank" href="https://twitter.com/msokola">Twitter</a>.</p>
<h2 id="heading-learn-react">Learn React</h2>
<p>Looking for a practical course to learn React? </p>
<p>🚀 <strong>Join my <a target="_blank" href="https://assets.mateu.sh/r/fcc-prettier-guide">React 18 Course on Udemy</a></strong>.</p>
<p>This course includes:</p>
<ul>
<li>🎥 5.5 hours on-demand video</li>
<li>📱 Access on mobile and TV</li>
<li>🗓️ Full lifetime access</li>
<li>🎓 Certificate of completion</li>
</ul>
<p>Click below to enroll.</p>
<p><a target="_blank" href="https://assets.mateu.sh/r/fcc-prettier-guide"><img src="https://assets.mateu.sh/assets/fcc-prettier-guide" alt="React 18 on Udemy" width="600" height="400" loading="lazy"></a><br><em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up React Testing Library With Next.js – A Step-by-Step Guide ]]>
                </title>
                <description>
                    <![CDATA[ In this guide, you will learn how to set up React Testing Library in Next.js. We'll also talk about why you should always test your React applications. I'll discuss the features and benefits of using the React Testing Library to test your React appli... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-react-testing-library-with-nextjs/</link>
                <guid isPermaLink="false">66bc4d1260ad5c1520c16689</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Thu, 07 Mar 2024 15:58:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/Testing-next-RTL.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this guide, you will learn how to set up React Testing Library in Next.js. We'll also talk about why you should always test your React applications.</p>
<p>I'll discuss the features and benefits of using the React Testing Library to test your React applications and how to configure it with Next.js. To conclude this tutorial, I will show you how I tested the board of my 2048 game. </p>
<p>To understand this guide, you don't need any deep knowledge, but it will be easier to learn if you know React basics. The ultimate goal is to set up tests for your Next.js apps, so understanding React will give you a smooth start with testing.</p>
<p>Let's get started!</p>
<h2 id="heading-why-does-testing-matter"><strong>Why Does Testing Matter?</strong></h2>
<p>To become a React developer, and increase your changes of finding a job, you need to learn about testing for several reasons:</p>
<p>First, testing confirms that your React application works as expected. It allows you to catch bugs and errors in the early stages of development before your company gets calls from angry customers. </p>
<p>Testing also allows you to refactor your code with confidence by ensuring that your changes don't break existing features. Without testing in place, after each refactoring you would need to manually click through your application to double-check. This would be so tedious and time-consuming. </p>
<p>Developers with decent testing skills are always more in-demand because they know how to design and build quality applications that can be maintained for many years.</p>
<h2 id="heading-what-is-react-testing-library"><strong>What is React Testing Library?</strong></h2>
<p>React Testing Library is a group of testing utilities designed to help you esure the correctness of your React and Next.js projects.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-05-at-10.09.49.png" alt="Image" width="600" height="400" loading="lazy">
<em>React Testing Library homepage</em></p>
<p>It doesn't matter if your project is written in TypeScript and uses React or Next.js – you can always take advantage of React Testing Library to test your application. It's easy to use and reduces the amount of code you need to write to prepare test cases.</p>
<p>React Testing Library was designed to simplify your life as a developer and help you write tests that don't make you frustrated. Your tests will only break when your app breaks, not its implementation.  </p>
<p>The best part is that React Testing Library isn't limited to unit tests. You can use it to prepare integration tests, end-to-end (E2E tests), and many others. That's why it is such a powerful tool.</p>
<h2 id="heading-how-to-set-up-react-testing-library-with-nextjs">How to Set Up React Testing Library with Next.js</h2>
<p>Using React Testing Library with Next.js is a very simple process. You only need four things:</p>
<ol>
<li>An existing Next.js project</li>
<li>Jest and React Testing Library installed with npm</li>
<li>Jest configured in your Next.js project</li>
<li>To write your first test</li>
</ol>
<p>Sounds simple, doesn't it?</p>
<p>The quickest way to create a new Next.js application is by typing <code>npx create-next-app@latest</code> in your command line. You will need to answer a few questions and the application will be automatically created for you.</p>
<p>If you have an existing Next.js project, you just need to install the testing suite using npm:</p>
<pre><code class="lang-bash">npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
</code></pre>
<p>In this guide, we'll use the Jest testing suite to execute tests which is a fairly common tool built by Facebook. If you wish to replace Jest with something else, you can easily use Vitest, Playwright, or Cypress – just <a target="_blank" href="https://nextjs.org/docs/app/building-your-application/testing">check out the Next.js docs for more details.</a></p>
<p>To configure Jest in Next.js, you need to create a <code>jest.config.js</code> file in your project root and paste the following content in (<a target="_blank" href="https://nextjs.org/docs/app/building-your-application/testing/jest">it's a boilerplate</a>):</p>
<pre><code class="lang-js"><span class="hljs-comment">// file: jest.config.js</span>
<span class="hljs-keyword">const</span> nextJest = <span class="hljs-built_in">require</span>(<span class="hljs-string">"next/jest"</span>);

<span class="hljs-keyword">const</span> createJestConfig = nextJest({
  <span class="hljs-attr">dir</span>: <span class="hljs-string">"./"</span>,
});

<span class="hljs-keyword">const</span> customJestConfig = {
  <span class="hljs-attr">setupFilesAfterEnv</span>: [<span class="hljs-string">"&lt;rootDir&gt;/jest.setup.js"</span>], <span class="hljs-comment">// &lt;= setup file here </span>
  <span class="hljs-attr">testEnvironment</span>: <span class="hljs-string">"jest-environment-jsdom"</span>,
};

<span class="hljs-built_in">module</span>.exports = createJestConfig(customJestConfig);
</code></pre>
<p>As you can see, the config file requires us to create one more file to make our tests work. This setup file will be included before every test and we'll use it to import React Testing Libary in every test so we don't need to do it manually. </p>
<p>Let's create the setup file now. It must be called <code>jest.setup.js</code> and should contain the following line:</p>
<pre><code class="lang-js"><span class="hljs-comment">// file: jest.setup.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom"</span>;
</code></pre>
<p>The configuration of your testing suite is almost complete. </p>
<h3 id="heading-how-to-create-the-npm-test-command">How to Create the <code>npm test</code> Command</h3>
<p>To finish configuration of our testing suite, we need to create an <code>npm test</code> command and link it with Jest and React Testing Library. We'll do that in <code>package.json</code> by adding a <code>test</code> command onto the <code>scripts</code> section:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"2048-in-react"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"0.2.0"</span>,
  <span class="hljs-attr">"homepage"</span>: <span class="hljs-string">"https://mateuszsokola.github.io/2048-in-react/"</span>,
  ...,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"next dev"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"next build"</span>,
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"next start"</span>,
    <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"next lint"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest --watch"</span> <span class="hljs-comment">// &lt;== HERE</span>
  },
  ...
}
</code></pre>
<p>Now whenever you run the <code>npm test</code> command you will run the testing suite:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-05-at-10.49.23.png" alt="Image" width="600" height="400" loading="lazy">
<em>Empty test summary.</em></p>
<p>The testing suite works, but the tests are still missing. This makes sense because we haven't created any tests yet. </p>
<h3 id="heading-how-to-test-components-using-react-testing-library">How to Test Components using React Testing Library</h3>
<p>Before we write our first test, let's create a directory where we'll store them. By default, tests are stored in the directory called <code>__tests__</code>. This name seems strange but it has a good reason to have double underscore pre- and postfixes. Thanks to these, your test directory will be always at the top of your project tree.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-05-at-11.09.58.png" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js project tree with the test directory at the top (place 1)</em></p>
<p>Now we are ready to create your first test.</p>
<p>We could make a random empty test that tests nothing, but I would rather use a real world example. Let's take one test from my 2048 game (<a target="_blank" href="https://github.com/mateuszsokola/2048-in-react">here's the source code</a>) – I picked one that ensures the game board is rendered correctly. </p>
<p>If you don't know the 2048 game, I will only tell that it is played on the 4 x 4 board. It means the game board needs have 16 cells (4 x 4 = 16).</p>
<p>Now let's create a new file called <code>board.test.jsx</code> in the test directory <code>__tests__</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// __tests__/compontents/board.test.jsx</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> Board <span class="hljs-keyword">from</span> <span class="hljs-string">"@/components/board"</span>;

describe(<span class="hljs-string">"Board"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should render board with 16 cells"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { container } = render(
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Board</span> /&gt;</span></span>
    );
    <span class="hljs-keyword">const</span> cellElements = container.querySelectorAll(<span class="hljs-string">".cell"</span>);

    expect(cellElements.length).toEqual(<span class="hljs-number">16</span>);
  });
});
</code></pre>
<p>As you can see, this test is rendering the board and checks that there are 16 DOM elements that have a <code>cell</code> class. Nothing more than that. If the number of cells is different, this test will fail.</p>
<p>Let's take a brief look into the terminal. It's all green and that means our test was implemented properly and it's passing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-05-at-10.52.45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Your first successful test</em></p>
<h2 id="heading-whats-next"><strong>What's Next?</strong></h2>
<p>Congratulations! Now you know how to set up one of the most popular testing libraries for React. I think it'll help you bring your Next.js application to a whole new level in terms of quality. </p>
<p>If you know how to build React apps, now you should double down on testing because this skill will help you to land your first job.</p>
<p>I hope this article helped you a lot. I'd mean the world to me if you share it on your social media.</p>
<p><a target="_blank" href="https://twitter.com/msokola">If you have any questions you can reach me on Twitter</a>.</p>
<h2 id="heading-learn-react-amp-nextjs">Learn React &amp; Next.js</h2>
<p>Learning Next.js can be intimidating and often frustrating. Most online courses are focused on React and Next.js features rather than building applications. That's why I created a course that will help you to learn React and Next.js while build a magnificent 2048 game from scratch!</p>
<p>I believe learning should be fun and unleash creativity. Would you rather build yet another TODO list instead of an awesome game? </p>
<p>You can join my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?couponCode=FREECODECAMP_">React and Next.js course on Udemy</a> and build the 2048 game along with me.</p>
<p>It’s the only course you need.</p>
<p><a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?couponCode=FREECODECAMP_"><img src="https://www.mateu.sh/udemy-freecodecamp.png" alt="Click to join React 18 &amp; Next.js course" width="600" height="400" loading="lazy"></a><br><em>Click to enroll</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Render an Array of Components in React ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, I will show you how using indices to render an array of components in React can be problematic. I'll also teach you how to mitigate array rendering issues with unique ids. As always, we'll work on a real world example and solve prob... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-render-array-of-components-in-react/</link>
                <guid isPermaLink="false">66bc4d10cd8a65d579e3a960</guid>
                
                    <category>
                        <![CDATA[ arrays ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Tue, 27 Feb 2024 19:18:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Array-components.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, I will show you how using indices to render an array of components in React can be problematic. I'll also teach you how to mitigate array rendering issues with unique ids.</p>
<p>As always, we'll work on a real world example and solve problem I stumbled across while building my 2048 Game in React. All the code snippets are inspired by this project. If you want to review the code before reading this article, you can <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">find it on GitHub</a>.</p>
<h2 id="heading-the-2048-game">The 2048 Game</h2>
<p>Let me explain the rules of the 2048 game first. The player must combine tiles that have the same numbers until they reach the number 2048. The tiles can contain only numbers that represent a power of two starting from 2 – this means 2, 4, 8, 16, 32, and so on – until they reach the number 2048. The board has dimensions of 4 x 4 tiles, so that it can fit up to 16 tiles.</p>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/demo-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>2048 Game Preview</em></p>
<p>In this article, I will only teach you how to render arrays in React and show you some best practices when comes to rendering lists in React components. </p>
<p>Unfortunately, we cannot create the entire game because it would make this article confusing. But if you want to do it from scratch, you should consider enrolling to my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">course on Udemy</a> where I will walk you through creating the 2048 Game with animations in React 18.</p>
<h2 id="heading-prerequisites"><strong>P</strong>rerequisites<em>**</em></h2>
<p>Before we start, make sure you know some basics of React. Nothing sophisticated – just be sure you've worked with React before, otherwise you might feel a bit lost.</p>
<p>If you don't yet know React, freeCodeCamp has a <a target="_blank" href="https://www.freecodecamp.org/news/learn-react-course/">5-hour React course for beginners</a> so feel free to watch it before reading this article. You can also enroll in my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course</a>.</p>
<p>Now let's get started.</p>
<h2 id="heading-how-to-render-array-elements"><strong>How to Render Array Elements</strong></h2>
<p>As I mentioned at the beginning, the game board has dimensions of 4 x 4 tiles. That means the best data structure to store tiles on the board will be a multidimensional array, like the one you see below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> board = [
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
]
</code></pre>
<p>Unfortunately, this data structure will be expensive, since it requires nested loops iterating across each other. That's why I decided to flatten this array into a one-dimensional one:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
</code></pre>
<p>As you can see, there are a lot of empty elements in this array, and it gives room for further improvements. We can reduce the amount of operations by replacing tile values with objects containing tile information. </p>
<p>For example, you can introduce a new type to store the meta data of every tile like this:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> TileModel = {
  position: [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>];
  value: <span class="hljs-built_in">number</span>;
};
</code></pre>
<p>As you can see, this data type makes tiles smart. Every tile will know its position and value. I decided to store the position as an array of two elements. These elements will represent <code>x</code> and <code>y</code> coordinates. Rather than pixels, I will use array indices on the board array I mentioned in the first step.</p>
<p>Now let's improve the <code>tilesOnBoard</code> array and make it store only existing tiles without empty values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [
    { <span class="hljs-attr">position</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
    { <span class="hljs-attr">position</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
]
</code></pre>
<p>Thanks to this simplification, I can render tiles by using the simple <code>map</code> functor that will iterate through all array elements and create Tile components out of them.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> renderTiles = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> tilesOnBoard.map(<span class="hljs-function">(<span class="hljs-params">tile: TileModel, index: number</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tile</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> {<span class="hljs-attr">...tile</span>} /&gt;</span></span>
  ));
};
</code></pre>
<p>Let's focus on the second argument of the <code>map</code> functor for a moment. As you can see, it uses the item index of the <code>tilesOnBoard</code> array. I am using it as a <code>key</code> property to initialize React components – in this case <code>Tile</code> components.</p>
<p>If you've never used <code>key</code> props, React needs keys to identify which elements have changed, are added, or are removed. Keys should be assigned to every item inside the array of components. </p>
<p>That's why I assigned array indices to all tiles. Unfortunately, array indices aren't the best unique identifiers, as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/array-indexes.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Strange behavior when array indices are used as key props</em></p>
<p>It might be hard to spot what's happening here, so let me briefly explain. Basically, React is reusing existing HTML elements to render new tiles. This isn't an intended behavior – instead, I should have removed merged tiles and created a new tile after every move. </p>
<p>But why is this happening? After the tiles are getting merged, a new tile is created, and that means the array still has two elements with the same array indices. </p>
<p>React uses a mechanism called the Virtual DOM to detect changes and modify elements on the DOM tree. Unfortunately, this mechanism is optimized for speed so that it doesn't analyze the entire component but only the <code>key</code> prop. This means React cannot differentiate the new tile creation from a style change on an existing div element. That's why we are experiencing this issue.  </p>
<p>To confirm that my reasoning is right, let's take a brief look at the <em>Element</em> tab in Chrome DevTools:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/reusing-html-elements.gif" alt="Image" width="600" height="400" loading="lazy">
<em>DOM Element reusability due to array indices used as key props</em></p>
<p>As you can see, two existing div elements only changed their style attributes but nothing was added or removed. This isn't an intended behavior, but it tells us that array indices are poor unique identifiers for React components.</p>
<p>If you aren't familiar with Chrome Developer Tools, you should read my article on implementing <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-mobile-swiping-component-in-react/">mobile touch events in React 18</a> where I do a deep dive on how to use it. </p>
<h2 id="heading-unique-identifiers-as-key-props"><strong>Unique Identifiers As Key Props</strong></h2>
<p>To fixing array rendering problems in React, we'll need to use some unique identifiers such as incremental ids, uuids, or others. To focus on the essentials, I decided to use a library called <code>uid</code>, which you can install by running the following in your terminal: </p>
<pre><code class="lang-bash">npm install --save uid
</code></pre>
<p>Now I need to modify tiles to support those identifiers. First, I added a new property <code>id</code> in the tile meta data type:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> TileModel = {
  id: <span class="hljs-built_in">string</span>;
  position: [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>];
  value: <span class="hljs-built_in">number</span>;
};
</code></pre>
<p>And I assigned an id to every element in the  <code>tilesOnBoard</code> array (here's where the <code>uid</code> library comes into play):</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [
    { <span class="hljs-attr">id</span>: uid(), <span class="hljs-attr">position</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
    { <span class="hljs-attr">id</span>: uid(), <span class="hljs-attr">position</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
]
</code></pre>
<p>The last thing I did was to change the <code>renderTiles</code> helper:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> renderTiles = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> tilesOnBoard.map(<span class="hljs-function">(<span class="hljs-params">tile: TileModel</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tile</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{tile.id}</span> {<span class="hljs-attr">...tile</span>} /&gt;</span></span>
  ));
};
</code></pre>
<p>As you can see, I removed an index argument from the <code>map</code> functor, and replaced the <code>key</code> prop with an unique id which I added to the tile meta data.</p>
<p>Now the 2048 game works like a charm:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/array-tile-ids.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, you learned that indices aren't the best option to render arrays of components in React and that they might lead to strange behaviors. If there is only one thing you should remember from this article it's that you should always use unique identifies as the <code>key</code> prop of React components.</p>
<p>Wanna learn more tricks like this one? You should join to my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course on Udemy</a>. I will teach you how to <strong>create 2048 game in React</strong> from scratch and show you solutions to the most common mistakes React developers make.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How To Use Node Version Manager In Your React Projects ]]>
                </title>
                <description>
                    <![CDATA[ In this guide,  you'll learn how to effectively manage multiple Node versions for different projects using Node Version Manager (NVM). Whether you're developing React, Angular, Vue.js, or Node applications, you can always use NVM to set up the projec... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-nvm-in-react-projects/</link>
                <guid isPermaLink="false">66bc4d1ecd8a65d579e3a966</guid>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 21 Feb 2024 13:51:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/React---NVM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this guide,  you'll learn how to effectively manage multiple Node versions for different projects using Node Version Manager (NVM). Whether you're developing React, Angular, Vue.js, or Node applications, you can always use NVM to set up the project and tailor it down to a specific Node version.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start, you need to have some <a target="_blank" href="https://www.freecodecamp.org/news/command-line-commands-cli-tutorial/">basic command line knowledge</a>. Nothing sophisticated, but make sure you've used it before reading this article otherwise you might feel a bit lost.</p>
<h2 id="heading-what-is-nvm">What Is NVM?</h2>
<p>Node Version Manager (NVM) is a command-line utility that enables you to manage multiple installations of Node.js and easily switch between them. </p>
<p>Whether you need to work on projects requiring different Node.js versions or want to experiment with the latest releases without affecting your existing setups, NVM provides an easy way to do so.</p>
<h2 id="heading-why-do-you-need-multiple-node-version">Why Do You Need Multiple Node Version?</h2>
<p>Nowadays, companies often build their application in the microservice architecture. This means that applications tend to be divided into many smaller services, where every service has its dedicated role. </p>
<p>It might sound like an over-engineering but there are a few benefits from this approach. In some cases, companies decide to build their applications using micro services to reach high availability and allow deployments without downtime. In the end, they can deploy one service at a time. </p>
<p>This approach also has downsides related to complexity and managing multiple projects. Imagine that your application is divided into many micro services, where the first one was built over 5 years ago. </p>
<p>The service is likely running on a legacy version of Node.js. In an ideal world, you would have to upgrade Node version to the newest version but it isn't always possible. In the end, the users' satisfaction comes first, and if they need new features, their needs must be fulfilled first. </p>
<p>Sometimes, a new feature might require you to introduce a new micro service. In this case, you should always try to use the newest Node version available. I will show you how to install multiple Node versions on your machine.</p>
<h2 id="heading-but-i-am-a-front-end-developer">But I Am a Front End Developer</h2>
<p>You'll still need NVM as a front end developer.</p>
<p>Nowadays, every JavaScript library and framework requires Node runtime and that's why you should manage Node versions for the frontend projects as well. The example project we will be using in this article is built in React 18 &amp; Next.js.</p>
<p>Let's get started.</p>
<h2 id="heading-how-to-install-nvm-on-linux-and-mac">How to Install NVM on Linux and Mac</h2>
<p>Installation on Linux and Mac is ultra simple. </p>
<p>Just open your terminal and run the following command:</p>
<pre><code class="lang-sh">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
</code></pre>
<p>This script will configure NVM on your machine and you will be able to use immediately. Nothing else is required. </p>
<p>Just try to run <code>nvm</code> command in your terminal, and you should see the following output: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-19-at-21.57.31.png" alt="Image" width="600" height="400" loading="lazy">
<em>nvm command output</em></p>
<p>If you see something like <code>nvm: command not found</code> then you can run these commands:</p>
<pre><code class="lang-sh"><span class="hljs-built_in">source</span> ~/.bashrc
<span class="hljs-built_in">source</span> ~/.zshrc
</code></pre>
<p>It's expected that one of them fails. This commands will reload you bash / zsh profile and enable NVM in your command prompt. </p>
<h2 id="heading-how-to-install-nvm-on-windows">How to Install NVM on Windows</h2>
<p>You can easily install NVM on Windows – just <a target="_blank" href="https://github.com/coreybutler/nvm-windows/releases">open the nvm-windows repository on GitHub</a>, scroll down to the <strong>Assets</strong> section, and download the <code>nvm-setup.exe</code> file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-19-at-22.04.05.png" alt="Image" width="600" height="400" loading="lazy">
<em>NVM Windows repository</em></p>
<p>Now the installer file will be downloaded. Once the download is completed, double-click on the <code>nvm-setup.exe</code> file and follow the instructions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/nvm-installer.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>NVM for Windows Installer by <a target="_blank" href="https://github.com/coreybutler">Corey Butler</a></em></p>
<p>After the installation, open PowerShell and run <code>nvm</code> command, you should see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/nvm-1.1.8-screenshot.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>NVM in PowerShell by <a target="_blank" href="https://github.com/coreybutler">Corey Butler</a></em></p>
<p>If <code>nvm</code> command returns <code>command not found</code> you should restart your computer to refresh your user settings.</p>
<h2 id="heading-how-to-set-node-version-for-your-project">How to Set Node Version For Your Project</h2>
<p>Now, we are reaching the root of this guide – setting dedicated Node version for your project. </p>
<p>First, create a <strong>.nvmrc</strong> file in your project root folder and specify the expected Node version. </p>
<p>It is <code>20.10.0</code> in my case:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-19-at-22.24.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>Node version in .nvmrc file</em></p>
<p>Now open your terminal and navigate to your project and run the <code>nvm use</code> command. NVM will automatically load the expected Node version by your project. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-19-at-22.27.04.png" alt="Image" width="600" height="400" loading="lazy">
<em>nvm use command</em></p>
<p>If you don't have the expected version on your machine, you'll be prompted to install it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-19-at-22.28.46.png" alt="Image" width="600" height="400" loading="lazy">
<em>prompt to install node version</em></p>
<p>In this case, you need to install required Node version by running <code>nvm install x.y.z</code>. Replace <code>x.y.z</code> with the expected Node version. It was <code>20.10.0</code>, in my case.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Working on multiple projects can be a hassle, especially when they require different Node versions. However, with NVM, changing the Node version is as quick as blinking an eye. </p>
<p>You should always use it, whether you're working alone on your personal project or with multiple colleagues on a large enterprise application.</p>
<p>If this article helped you, please share it on your social media or give me a <a target="_blank" href="https://twitter.com/msokola">shout-out on Twitter</a>. Thank you!</p>
<h2 id="heading-learn-react-18-amp-nextjs"><strong>Learn React 18 &amp; Next.js</strong></h2>
<p>This article is a part of my React and Next.js course on Udemy. I will help you to get started with React and Next.js by creating a 2048 Game with awesome animations. I believe creating games makes learning more fun, and you'll have something cool to show your friends.</p>
<p>👇👇👇👇</p>
<h3 id="heading-enroll-to-my-course-on-udemyhttpswwwudemycomcourse2048-in-react-and-nextjsreferralcodeac3fd6336bab9c402106"><strong>🧑‍🎓</strong> Enroll to <strong>my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">course on Udemy</a></strong></h3>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Custom React Hook – a Hands-on Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ If you have been working with React, I bet you've had the opportunity to use hooks. But have you ever tried to create your own hook?  Today I will help you create your first custom hook and explain how they can improve your codebase. Why Create Custo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-custom-react-hooks/</link>
                <guid isPermaLink="false">66bc4d01e35f27b3539506e4</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 14 Feb 2024 17:39:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Custom-hooks.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you have been working with React, I bet you've had the opportunity to use hooks. But have you ever tried to create your own hook? </p>
<p>Today I will help you create your first custom hook and explain how they can improve your codebase.</p>
<h2 id="heading-why-create-custom-hooks">Why Create Custom Hooks?</h2>
<p>You might be wondering – why would I even want to create new React hook? In the end, React has all the essential hooks in place and anything else seems slightly excessive. That's true React comes with many powerful hooks, but did you know that custom hooks can improve the quality of your code? </p>
<p>Imagine you have a piece of React code that's used across many components. As a programmer, you don't want to repeat yourself, and you make repeated code reusable as much as possible. That's why it's a good idea to wrap those snippets into utilities, components, or custom hooks.</p>
<p>Crafting your own hooks will not only simplify your components, but also significantly reduce the size of your codebase. Remember, less code typically means better readability and lower code complexity, too.</p>
<p>I hope I have you "hooked" now – pun intended.</p>
<h2 id="heading-prerequisites"><strong>🛠️ P</strong>rerequisites<em>**</em></h2>
<p>Before you read this guide, you need to be familiar with React. Don't get me wrong – you don't need to be an expert, but some understanding of the basics are necessary. </p>
<p>If you don't feel like a strong enough React dev, you might consider enrolling in <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">my Udemy course</a> where you will learn React 18 by creating a 2048 game from scratch. You can find more details and a discount code at the end of this tutorial.</p>
<p>Also, you can check out <a target="_blank" href="https://www.freecodecamp.org/news/learn-react-key-concepts/">this free tutorial</a> where you'll learn the key concepts you need to get started with React.</p>
<h2 id="heading-your-first-custom-hook-usepreviousprops">🪝 Your First Custom Hook – <code>usePreviousProps</code></h2>
<p>In my articles, I'm always trying to use real world examples – and this guide will not be any different. We will create a hook responsible for tracking previous values of component props. This means we will build a custom hook called <code>usePreviousProps</code> from scratch. </p>
<p>One of the most common use cases for a hook like this is when you're dealing with animations. For instance, imagine that you need to highlight a newly created element. How could you determine if it's new without comparing current values to previous ones? That's where our new hook comes into play.</p>
<p>The benefits of a custom hook like ours might be a bit vague, but it's a really powerful tool. Literally, the custom <code>usePreviousProps</code> hook we'll create today is used in some of my open source projects, and even a few production-grade apps I've built. So you can be sure this hook has a real use case, and it only takes 12 lines to implement.</p>
<p>Now let's get our hands dirty!</p>
<h2 id="heading-how-to-create-a-custom-hook">🪚 How to Create a Custom Hook</h2>
<p>First, we need to create a new file in the <code>hooks</code> directory of your project – I decided to call it <code>use-previous-props.js</code>. </p>
<p>Keep in mind that React hooks rarely use JSX syntax (HTML), which is why we are using the <code>.js</code> extension. If you need to enable JSX syntax need to change the extension to <code>.jsx</code>. But think twice before doing this – if you really need JSX, you should probably crate a standalone component instead of a hook.</p>
<pre><code class="lang-js"><span class="hljs-comment">// file: hooks/use-previous-props.js</span>

<span class="hljs-keyword">import</span> { useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">usePreviousProps</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">const</span> ref = useRef();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    ref.current = value;
  });

  <span class="hljs-keyword">return</span> ref.current;
}
</code></pre>
<p>As you can see, our hook is very similar to a regular functional component. The only difference is the <code>return</code> statement – it returns a JavaScript value instead of an HTML element.</p>
<p>React hooks often return values, functions, or both. For example, the <code>useState</code> hook returns an array with two elements: the current state value and a function to update that value. </p>
<p>Now let me explain how the <code>usePreviousProps</code> hook actually works:</p>
<ul>
<li><code>const ref = useRef()</code> is used to persist the reference across re-renders of the component. In our case, we will use it to store the previous value. </li>
<li>The <code>useEffect</code> hook will update <code>ref.current</code> value whenever the component re-renders. This means that when <code>value</code> changes, the <code>ref.current</code> value will be updated to store the most recent value of the prop. Importantly, all of this happens after the component finishes rendering, so it stores the previous value during the re-render.</li>
<li><code>return ref.current</code> returns the value from the <code>ref</code> reference.</li>
</ul>
<p>Now our custom <code>usePreviousProps</code> hook is ready to use!</p>
<h2 id="heading-how-to-use-a-custom-hook">😎 How to Use a Custom Hook</h2>
<p>Last week I published the tutorial <a target="_blank" href="https://www.freecodecamp.org/news/create-animations-in-react/">How to Create Animations in React 18</a>.</p>
<p>If you didn't read my last tutorial, it includes the custom <code>usePreviousProps</code> hook to create highlighting animations:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/hightlight-3.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Highlighting animation</em></p>
<p>Here is the code responsible for this animation:</p>
<pre><code class="lang-jsx"><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">Tile</span>(<span class="hljs-params">{ value }</span>) </span>{
  <span class="hljs-keyword">const</span> [scale, setScale] = useState(<span class="hljs-number">1</span>);

  <span class="hljs-keyword">const</span> previousValue = usePreviousProps(value);
  <span class="hljs-keyword">const</span> hasChanged = previousValue !== value;

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (hasChanged) {
      setScale(<span class="hljs-number">1.1</span>);
      <span class="hljs-built_in">setTimeout</span>(
          <span class="hljs-function">() =&gt;</span> setScale(<span class="hljs-number">1</span>), 
          <span class="hljs-number">100</span> <span class="hljs-comment">/* 100ms == 0.1s */</span>
      );
    }
  }, [hasChanged, setScale]);

  <span class="hljs-keyword">const</span> style = {
    <span class="hljs-attr">transform</span>: <span class="hljs-string">`scale(<span class="hljs-subst">${scale}</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">"tile"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{style}</span>&gt;</span>
      {value}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Let's focus on this line: <code>const previousValue = usePreviousProps(value)</code>.</p>
<p>Here, <code>previousValue</code> contains the previous value for this component. If it's a new component it returns <code>undefined</code>.</p>
<p>On the next line, the <code>hasChanged</code> constant helps determine if the component should be highlighted. If it's new and returned <code>undefined</code> earlier, it triggers the highlighting animation.</p>
<p>A few lines later, I declared the <code>useEffect</code> hook that will check if a component has changed its value. If that happened, React will execute the highlighting animation.</p>
<h2 id="heading-summary"><strong>🏁 Summary</strong></h2>
<p>Today you've learned that React hooks are fairly similar to functional components. The only difference is their output, where they return JavaScript values, arrays, or functions rather than JSX elements.</p>
<p>As you can see, creating custom hooks isn't rocket science, and I hope I've inspired you to experiment and create one of your own.</p>
<p>If this article helped you, please share it on your social media or give me a <a target="_blank" href="https://twitter.com/msokola">shout-out on Twitter</a>. Thank you!</p>
<h2 id="heading-would-you-like-to-build-your-own-2048-game"><strong>🏫 </strong>Would You Like to Build Your Own 2048 Game?<em>**</em></h2>
<p>If you want to improve your React skills, consider joining my online course on Udemy. I will help you to get started with React 18 by building a fully-functional 2048 Game. I believe creating games makes learning more fun, and you'll have something cool to show your friends. </p>
<p>Also, I'm giving a 50% discount for freeCodeCamp readers. Just use the code <strong>50DISCOUNT</strong> to enroll.</p>
<p>👇👇👇👇</p>
<h3 id="heading-join-my-react-18-course-on-udemyhttpswwwudemycomcourse2048-in-react-and-nextjsreferralcodeac3fd6336bab9c402106"><strong>🧑‍🎓 Join my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course on Udemy</a></strong></h3>
<p>What you'll learn:</p>
<ul>
<li>How to build 2048 game with React 18 and Next.js.</li>
<li>Essential React hooks such as useState, useRef, useCallback, useEffect, and many more.</li>
<li>Managing state using Reducer and React Context.</li>
<li>How to create responsive mobile apps that support touch events (like mobile swiping).</li>
<li>Integrate TypeScript into your React projects.</li>
<li>Testing React apps.</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Animations in React 18 ]]>
                </title>
                <description>
                    <![CDATA[ We are surrounded by gorgeous web applications. Sometimes I catch myself admiring visual effects on some website and wondering how they were made.  Well today I'll show you how you can create awesome CSS animations in React 18. As always, we'll work ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-animations-in-react/</link>
                <guid isPermaLink="false">66bc4cf83fc58765eaa843c6</guid>
                
                    <category>
                        <![CDATA[ animations ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Thu, 08 Feb 2024 23:51:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Animations-splash--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We are surrounded by gorgeous web applications. Sometimes I catch myself admiring visual effects on some website and wondering how they were made. </p>
<p>Well today I'll show you how you can create awesome CSS animations in React 18.</p>
<p>As always, we'll work on the real world example but we'll just focus on the animations only to avoid confusion. If you want to see the final results applied to a proper application, then don't worry. I've attached the source code of a pet project so feel free to <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">play with it</a>. </p>
<p>Before we start, I need to give you some context – I designed those animations for my 2048 Game in React. This game is a part of my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">online course on Udemy</a> but I will tell you more about it at the end of this article.  </p>
<p>You can find the <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">source code on GitHub</a>. Here's the final result of what we'll be creating:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/all-animations.gif" alt="Image" width="600" height="400" loading="lazy">
<em>All animations of 2048-in-react</em></p>
<h2 id="heading-prerequisites"><strong>🛠️ P</strong>rerequisites<em>**</em></h2>
<p>Before we start, make sure you know some basics of React and CSS. It would be great if you are familiar CSS transitions but it isn't necessary. Actually I'm hoping this article will encourage you to go down that rabbit hole on your own. Believe me – nothing is more rewarding than users admiring your work. </p>
<p>Also, you don't need any tools, but if you want to run the example project on your computer, then you will need to install <a target="_blank" href="https://nodejs.org/en">Node.js</a> first.</p>
<h2 id="heading-quick-introduction">🕹️ <strong>Quick Introduction</strong></h2>
<p>If you aren't familiar with the 2048 game, here's the gist: the player must combine tiles containing the same numbers until they reach the number 2048. The tiles can contain only numbers that represent a power of two starting from 2 – this means 2, 4, 8, 16, 32, and so on. The board has dimension of 4 x 4 tiles, so that it can fit up to 16 tiles.</p>
<p>Let me briefly show you what animations I prepared for the game's users:</p>
<p>The first animation is supposed to visualize the tile movement.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/slide.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The "tile sliding" animation</em></p>
<p>The game would look janky if tiles disappeared and popped up in different places. CSS transitions help make the movement smooth for users.</p>
<p>The second animation highlights tile creation and their merges.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/hightlight-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The "tile highlighting" animation</em></p>
<p>This animation helps users spot tiles that are changed after the movement.</p>
<p>I think that's all I need to tell you about the project. Let's get our hands dirty!</p>
<h2 id="heading-how-to-create-the-highlighting-animation">🌟 How to Create the Highlighting Animation</h2>
<p>We'll start with the animation responsible for highlighting changes. I must admit I had a hard time to find a "beautiful" way to visualize it. The main objective was to bring the user's focus to tiles that changed their values or were created. I decided to rescale those tiles because it didn't want the animation to be too "intrusive".</p>
<p>So how is this going to work? First, we'll increase the size of the tile to 110%. Once the tile reaches 110% of its original size, we will downscale it back to 100%. The entire animation will last 0.2s (0.1s upscale, 0.1s downscale). I think that's enough to show the user's updated elements.</p>
<p>We can accomplish this animation using the following CSS transitions:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.tile</span> {
  // ...
  <span class="hljs-attribute">transition-property</span>: transform;
  <span class="hljs-attribute">transition-duration</span>: <span class="hljs-number">100ms</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">1</span>);
}
</code></pre>
<p>Brief explanation of those CSS properties:</p>
<ul>
<li><code>transition-property</code> – defines the property on which the transition will be applied. In our case, we want to animate the transformation – the change of the element's size. </li>
<li><code>transition-duration</code> – defines transition duration. In our case – 0.1s.</li>
<li><code>transform</code> – this property allows us to rotate, scale, skew, or translate an element. Side note: the <code>scale(1)</code> means 100%, and we will use it as a default value.</li>
</ul>
<p>The CSS transition is ready. Now we need to implement rescaling in React. </p>
<pre><code class="lang-js"><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">Tile</span>(<span class="hljs-params">{ value }</span>) </span>{
  <span class="hljs-keyword">const</span> [scale, setScale] = useState(<span class="hljs-number">1</span>);

  <span class="hljs-keyword">const</span> previousValue = usePreviousProps(value);
  <span class="hljs-keyword">const</span> hasChanged = previousValue !== value;

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (hasChanged) {
      setScale(<span class="hljs-number">1.1</span>);
      <span class="hljs-built_in">setTimeout</span>(
          <span class="hljs-function">() =&gt;</span> setScale(<span class="hljs-number">1</span>), 
          <span class="hljs-number">100</span> <span class="hljs-comment">/* 100ms == 0.1s */</span>
      );
    }
  }, [hasChanged, setScale]);

  <span class="hljs-keyword">const</span> style = {
    <span class="hljs-attr">transform</span>: <span class="hljs-string">`scale(<span class="hljs-subst">${scale}</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">"tile"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{style}</span>&gt;</span>
      {value}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Let me briefly explain this code:</p>
<ol>
<li>It sets the initial scale using the <code>useState</code> hook. By default, it's <code>1</code> to reflect 100% of the tile size.</li>
<li>We take advantage of the <code>usePreviousProps</code> hook to retrieve the previous value of the tile. If the tile is freshly created, the previous value will be <code>undefined</code>.</li>
<li>The <code>useEffect</code> hook plays a key role in our animation – it's checking if the tile's value has changed. If yes, it will scale it up to 110% and after 0.1s it will set it back to 100%.</li>
<li>The <code>style</code> constant is used to inject inline CSS attributes into the <code>div</code> element. </li>
</ol>
<p>And the result is the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/hightlight.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tile creation (aka "hightlighting")</em></p>
<h2 id="heading-how-to-create-the-sliding-animation">🛝 How to Create the Sliding Animation</h2>
<p>The second animation is responsible for tile movements. I hope you agree with me that users might feel confused if they can't trace tiles moving across the board. After every move they would need to analyze the entire board again. It'd be a poor user-experience.</p>
<p>Let's think about how we can fix it. We could definitely take advantage of CSS properties responsible for positioning, such as <code>left</code> and <code>top</code>. If we follow this approach, we need to add a few additional CSS transitions. Let's do it.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.tile</span> {
  <span class="hljs-attribute">position</span>: absolute;
  // ...
  <span class="hljs-attribute">transition-property</span>: left, top, transform;  // <span class="hljs-attribute">added</span>: left, top
  transition-duration: <span class="hljs-number">250ms</span>, <span class="hljs-number">250ms</span>, <span class="hljs-number">100ms</span>; // <span class="hljs-attribute">added</span>: <span class="hljs-number">250ms</span>, <span class="hljs-number">250ms</span>
  transform: <span class="hljs-built_in">scale</span>(<span class="hljs-number">1</span>);
}
</code></pre>
<p>Once we've declared the transitions, we can implement the logic responsible for tile movement.</p>
<pre><code class="lang-js"><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">Tile</span>(<span class="hljs-params">{ value, position }</span>) </span>{
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">const</span> boardWidthInPixels = <span class="hljs-number">464</span>; 
  <span class="hljs-keyword">const</span> tileCount = <span class="hljs-number">4</span>;

  <span class="hljs-keyword">const</span> positionToPixels = <span class="hljs-function">(<span class="hljs-params">position</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (position / tileCount) * boardWidthInPixels;
  };    

  <span class="hljs-keyword">const</span> style = {
    <span class="hljs-attr">top</span>: positionToPixels(position[<span class="hljs-number">0</span>]),
    <span class="hljs-attr">left</span>: positionToPixels(position[<span class="hljs-number">1</span>]),      
    <span class="hljs-attr">transform</span>: <span class="hljs-string">`scale(<span class="hljs-subst">${scale}</span>)`</span>
  };

  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>As you can see, the equation in the <code>positionToPixels</code> function needs to know the position of the tile, the total number of tiles per row and column, and the total board length in pixels (width or height – same, it is a square). The calculated value is passed down to the <code>style</code> constant which we passed down to the div element in the previous step.</p>
<p>The result is the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/slide-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Animation for tile movement</em></p>
<h2 id="heading-summary"><strong>🏁 Summary</strong></h2>
<p>Adding CSS transitions into your React project may seem intimidating at first but it really isn't. As you can see, just a few lines of code significantly improved the user-experience of my game. </p>
<p>Keep in mind that while animations can indeed improve user experience, they can also ruin it. Always aim to find the right balance when you are applying them. It takes some practice, and that's why I hope this article encouraged you to experiment on your own.</p>
<p>The best way to learn is by practicing and learning from others. That's why you should check the <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">source code on my 2048 Game on Github</a>. Don't forget to give it a star 🌟 . It's the easiest way to bookmark it in your profile so you never lose it. </p>
<p>If this article helped you, please share it on your social media or give me a <a target="_blank" href="https://twitter.com/msokola">shout-out on Twitter</a>. Thank you!</p>
<h2 id="heading-would-you-like-to-build-your-own-2048-game">🏫 <strong>Would You Like to Build Your Own 2048 Game?</strong></h2>
<p>As I told you at the beginning, I created an online course on Udemy where I teach how to create a fully-functional 2048 Game in React 18. I'm giving 50% discount for freeCodeCamp readers. Just use the code <strong>50DISCOUNT</strong> to enroll.</p>
<h3 id="heading-join-my-react-18-course-on-udemyhttpswwwudemycomcourse2048-in-react-and-nextjsreferralcodeac3fd6336bab9c402106"><strong>🧑‍🎓 Join my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course on Udemy</a></strong></h3>
<p>What you'll learn:</p>
<ul>
<li>How to build 2048 game with React 18 and Next.js.</li>
<li>Essential React hooks such as useState, useRef, useCallback, useEffect, and many more.</li>
<li>Managing state using Reducer and React Context.</li>
<li>How to create responsive mobile apps that support touch events (like mobile swiping). </li>
<li>Integrate TypeScript into your React projects.</li>
<li>Testing React apps.</li>
</ul>
<p>I created this course because I believe programming should be fun and unleash creativity. Rather than build yet another TODO list or a shopping cart, let's create something that you can show to your friends or maybe even a hiring manager!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Mobile Swiping Component in React ]]>
                </title>
                <description>
                    <![CDATA[ Everyone wants to be able to access the web from their mobile phones these days. So it's important to consider the accessibility of your web app on Android and iPhones.  The most difficult part is building the navigation – and swiping in particular c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-mobile-swiping-component-in-react/</link>
                <guid isPermaLink="false">66bc4cff3fc58765eaa843c8</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Fri, 02 Feb 2024 17:43:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/MobileSwiping-splash--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Everyone wants to be able to access the web from their mobile phones these days. So it's important to consider the accessibility of your web app on Android and iPhones. </p>
<p>The most difficult part is building the navigation – and swiping in particular can cause a lot of headaches. There are libraries you can use to help with this, but why not build it on your own? </p>
<p>In this tutorial, I will teach you how to create your own mobile swiping component in React. You can do it in 50 lines of JavaScript. </p>
<p>Initially, I created this component for my pet project, the 2048 Game in React, and have now decided to share how I did it. </p>
<p>If you want to try it out before reading the whole article, you can <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">play the game here</a> (use your mobile device). In this tutorial, we will focus on mobile swiping only.  </p>
<p>You can find the following resources on GitHub:</p>
<ul>
<li>📱 <a target="_blank" href="https://gist.github.com/mateuszsokola/80b2a939ad521eb26f488fcdc659e0ca">Source code of the component</a></li>
<li>🕹️ <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">Source code of 2048 Game</a></li>
</ul>
<p>Here is the sneak peak (the quality isn't the best because I was trying to keep the size small):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/MobilePreview-low--1-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The final result in my pet project</em></p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-how-to-simulate-a-mobile-device-in-your-browser">How to Simulate a Mobile Device in Your Browser</a></li>
<li><a class="post-section-overview" href="#heading-the-mobileswiper-component">The MobileSwiper Component</a></li>
<li><a class="post-section-overview" href="#heading-lets-make-it-swipable">Let's Make it Swipable</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ol>
<h2 id="heading-prerequisites">🛠️ P<strong>rerequisites</strong></h2>
<p>Before we start, make sure you know a little bit about React and JavaScript. You don't need any sophisticated tools, but if you want to run the example project on your computer, then you will need to install <a target="_blank" href="https://nodejs.org/en">Node.js</a> first.</p>
<p>Also, I'm using <a target="_blank" href="https://www.google.com/chrome/">Google Chrome</a> to simulate a mobile device on my computer. Keep in mind that if you use any different browser, then the steps might be slightly different.</p>
<h2 id="heading-how-to-simulate-a-mobile-device-in-your-browser">🔍 <strong>How to Simulate a Mobile Device in Your Browser</strong></h2>
<p>Before we start coding, I need to show you how to simulate a mobile device in Google Chrome. </p>
<p>Open your browser, right click on your page, and choose "<em>Inspect</em>" from the dropdown menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/MobileSwiper-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to open Developer Tools in Google Chrome</em></p>
<p>Your browser view should now be split into two parts. The second part contains Chrome's Developer Tools. </p>
<p>Now, click on the "laptop &amp; mobile" icon (1 in the image below) in top left corner of the Developer tools. Then select the "Dimensions" (2) of the device you want to simulate. I chose iPhone SE because this device has the smallest resolution supported by my game.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/MobileSwiper-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choose device dimensions in Developer Tools (Google Chrome)</em></p>
<p>Now we are ready to simulate swiping by using our mouse or touchpad. Just pay attention to the GIF below – my cursor turned into a circle which is supposed to visualize the area covered by a person's finger. </p>
<p>When I try to swipe, my browser thinks I am actually scrolling through the website. In my case, this isn't an expected behavior. I would like to instead use swipes to play the game.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/game-v2-broken.gif" alt="Image" width="600" height="400" loading="lazy">
<em>By default, scrolling events are associated with swipes</em></p>
<h2 id="heading-the-mobileswiper-component">🤓 The MobileSwiper Component</h2>
<p>First, we need to create a <strong>mobile-swiper</strong>.<strong>jsx</strong> file. In this file, we declare a standard React component. Our component needs to accept two properties – <code>children</code> and <code>onSwipe</code>.</p>
<pre><code class="lang-js"><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">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>   
}
</code></pre>
<p>Let me briefly explain them:</p>
<ul>
<li><code>children</code> allows <code>MobileSwiper</code> to accept and render any content placed between its opening and closing tags. It enables you to inject the entire board inside this component – but we will get to this later.</li>
<li><code>onSwipe</code> is a callback that our component will trigger each time the user swipes within the "swipable" area. </li>
</ul>
<p>Let's define the swipable area now. First, you need to add a reference to the DOM element in which you want to allow swiping. You can do this by using the <code>useRef</code> hook. So declare a constant called <code>wrapperRef</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</span>)

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>

}
</code></pre>
<p>Side note: The <code>useRef</code> is a React Hook that lets you reference a value that’s not needed for rendering. It’s particularly common to use it to manipulate the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API">DOM</a>. React has built-in support for this.</p>
<p>Now you just need to return the <code>&lt;div /&gt;</code> that references the constant you created using the <code>useRef</code> hook.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</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">ref</span>=<span class="hljs-string">{wrapperRef}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>Let's think for a moment how we can detect swiping. I believe the easiest way is comparing the starting and ending position of the user's finger. </p>
<p>This means we need to store the initial position of the user's finger in state. Basically, we will store <code>x</code> and <code>y</code> coordinates using the <code>useState</code> hook.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</span>)
    <span class="hljs-keyword">const</span> [startX, setStartX] = useState(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">const</span> [startY, setStartY] = 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">ref</span>=<span class="hljs-string">{wrapperRef}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>Now we need to create two event callbacks:</p>
<ul>
<li><code>handleTouchStart</code> will set the starting position of the user's finger.</li>
<li><code>handleTouchEnd</code> will set the final position of the user's finger and calculate the shift (delta) based on the starting point.</li>
</ul>
<p>Let's start with the <code>handleTouchStart</code> event handler:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useCallback, useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</span>)
    <span class="hljs-keyword">const</span> [startX, setStartX] = useState(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">const</span> [startY, setStartY] = useState(<span class="hljs-number">0</span>)    

    <span class="hljs-keyword">const</span> handleTouchStart = useCallback(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!wrapperRef.current.contains(e.target)) {
              <span class="hljs-keyword">return</span>
        }

        e.preventDefault()

        setStartX(e.touches[<span class="hljs-number">0</span>].clientX)
        setStartY(e.touches[<span class="hljs-number">0</span>].clientY)
      }, [])

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{wrapperRef}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>Let me briefly explain it:</p>
<ol>
<li>I wrapped this helper into the <code>useCallback</code> hook to cache and improve its performance. If you don't know this hook, you can read about it in the official <a target="_blank" href="https://react.dev/reference/react/useCallback">React docs</a>.</li>
<li>The <code>if</code> statement checks if the user is swiping within the swipable area. If they swipe outside of this area, we will proceed with scrolling.</li>
<li><code>e.preventDefault()</code> disables the default scrolling event.</li>
<li>The last two lines store <code>x</code> and <code>y</code> coordinates in state.</li>
</ol>
<p>Now let's implement the <code>handleTouchEnd</code> event handler:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useCallback, useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</span>)
    <span class="hljs-keyword">const</span> [startX, setStartX] = useState(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">const</span> [startY, setStartY] = useState(<span class="hljs-number">0</span>)    

    <span class="hljs-keyword">const</span> handleTouchStart = useCallback(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!wrapperRef.current.contains(e.target)) {
              <span class="hljs-keyword">return</span>
        }

        e.preventDefault()

        setStartX(e.touches[<span class="hljs-number">0</span>].clientX)
        setStartY(e.touches[<span class="hljs-number">0</span>].clientY)
    }, [])

      <span class="hljs-keyword">const</span> handleTouchEnd = useCallback(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!wrapperRef.current.contains(e.target)) {
            <span class="hljs-keyword">return</span>
        }

        e.preventDefault()

        <span class="hljs-keyword">const</span> endX = e.changedTouches[<span class="hljs-number">0</span>].clientX
        <span class="hljs-keyword">const</span> endY = e.changedTouches[<span class="hljs-number">0</span>].clientY
        <span class="hljs-keyword">const</span> deltaX = endX - startX
        <span class="hljs-keyword">const</span> deltaY = endY - startY

        onSwipe({ deltaX, deltaY })
    }, [startX, startY, onSwipe])

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{wrapperRef}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>As you can see, steps 1-3 are exactly the same as in the <code>handleTouchStart</code> callback. Now, we'll take the final <code>x</code> and <code>y</code> coordinates of user's finger and deduct the initial <code>x</code> and <code>y</code> from those. Thanks to that we can calculate horizontal and vertical shift of the user's finger (deltas).</p>
<p>Then we pass those deltas onto the <code>onSwipe</code> callback. If you remember, we declared it in the component's props at the beginning. </p>
<p>Now we need to connect those callbacks into the event listener. To do so, we can use the <code>useEffect</code> hook from React.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useCallback, useEffect, useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-keyword">const</span> wrapperRef = useRef(<span class="hljs-literal">null</span>)
    <span class="hljs-keyword">const</span> [startX, setStartX] = useState(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">const</span> [startY, setStartY] = useState(<span class="hljs-number">0</span>)    

    <span class="hljs-keyword">const</span> handleTouchStart = useCallback(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!wrapperRef.current.contains(e.target)) {
              <span class="hljs-keyword">return</span>
        }

        e.preventDefault()

        setStartX(e.touches[<span class="hljs-number">0</span>].clientX)
        setStartY(e.touches[<span class="hljs-number">0</span>].clientY)
      }, [])

      <span class="hljs-keyword">const</span> handleTouchEnd = useCallback(
    <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!wrapperRef.current.contains(e.target)) {
            <span class="hljs-keyword">return</span>
        }

        e.preventDefault()

        <span class="hljs-keyword">const</span> endX = e.changedTouches[<span class="hljs-number">0</span>].clientX
        <span class="hljs-keyword">const</span> endY = e.changedTouches[<span class="hljs-number">0</span>].clientY
        <span class="hljs-keyword">const</span> deltaX = endX - startX
        <span class="hljs-keyword">const</span> deltaY = endY - startY

        onSwipe({ deltaX, deltaY })
    }, [startX, startY, onSwipe])   

     useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"touchstart"</span>, handleTouchStart)
        <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"touchend"</span>, handleTouchEnd)

        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"touchstart"</span>, handleTouchStart)
            <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"touchend"</span>, handleTouchEnd)
        }
      }, [handleTouchStart, handleTouchEnd])

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{wrapperRef}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>You can read more about the <code>useEffect</code> hook in the official <a target="_blank" href="https://react.dev/reference/react/useEffect">React docs</a>.</p>
<p>The <strong>MobileSwiper</strong> component is ready now.</p>
<h2 id="heading-lets-make-it-swipable">🔌 Let's Make It Swipable</h2>
<p>The last thing we need to do is hook our component to the application. As I mentioned, I will be using this component in my 2048 Game (<a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">Source code</a>). If you want to use it somewhere else, the <code>handleSwipe</code> helper and the MobileSwiper component will remain the same.</p>
<p> Let's plug it into the Board component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useCallback, useContext, useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Tile <span class="hljs-keyword">as</span> TileModel } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/models/tile"</span>
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"@/styles/board.module.css"</span>
<span class="hljs-keyword">import</span> Tile <span class="hljs-keyword">from</span> <span class="hljs-string">"./tile"</span>
<span class="hljs-keyword">import</span> { GameContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/context/game-context"</span>
<span class="hljs-keyword">import</span> MobileSwiper <span class="hljs-keyword">from</span> <span class="hljs-string">"./mobile-swiper"</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">Board</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { getTiles, moveTiles, startGame } = useContext(GameContext);

    <span class="hljs-comment">// ... removed irrelevant parts ...</span>

    <span class="hljs-keyword">const</span> handleSwipe = useCallback(<span class="hljs-function">(<span class="hljs-params">{ deltaX, deltaY }</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.abs(deltaX) &gt; <span class="hljs-built_in">Math</span>.abs(deltaY)) {
            <span class="hljs-keyword">if</span> (deltaX &gt; <span class="hljs-number">0</span>) {
                moveTiles(<span class="hljs-string">"move_right"</span>)
            } <span class="hljs-keyword">else</span> {
                moveTiles(<span class="hljs-string">"move_left"</span>)
            }
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">if</span> (deltaY &gt; <span class="hljs-number">0</span>) {
                moveTiles(<span class="hljs-string">"move_down"</span>)
            } <span class="hljs-keyword">else</span> {
                moveTiles(<span class="hljs-string">"move_up"</span>)
            }
        }
    }, [moveTiles])

     <span class="hljs-comment">// ... removed irrelevant parts ...</span>

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MobileSwiper</span> <span class="hljs-attr">onSwipe</span>=<span class="hljs-string">{handleSwipe}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.board}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.tiles}</span>&gt;</span>{renderTiles()}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.grid}</span>&gt;</span>{renderGrid()}<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">MobileSwiper</span>&gt;</span></span>
      )
}
</code></pre>
<p>Let's start with the <code>handleSwipe</code> handler. As you can see, we're comparing if <code>deltaX</code> is greater than <code>deltaY</code> to decide if the user swiped horizontally (left / right) or vertically (top / bottom).</p>
<p>If it was a horizontal swipe, then:</p>
<ul>
<li>negative <code>deltaX</code> means they swiped to the left.</li>
<li>positive <code>deltaX</code> means they swiped to the right.</li>
</ul>
<p>If it was a vertical swipe, then:</p>
<ul>
<li>negative <code>deltaY</code> means they swiped up.</li>
<li>positive <code>deltaY</code> means they swiped down.</li>
</ul>
<p>Now, let's focus on the MobileSwiper component. You can find it in the <code>return</code> statement. We're passing the <code>handleSwipe</code> helper to the <code>onSwipe</code> property and wrapping the entire HTML code of the Board component to enable swiping on it.</p>
<p>Now when we try it out, the result isn't ideal. Scrolling events are mixed with mobile swipes, as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/game-v2-passive-true.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Board with duplicated events – swipes and scrolling</em></p>
<p>This is happening because modern browsers use passive event listeners to improve the scrolling experience on mobile devices. This means that the <code>preventDefault</code> we added to our event callbacks never happens. </p>
<p>To disable scrolling behavior, we need to disable passive listeners on the MobileSwiper component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useCallback, useEffect, useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MobileSwiper</span>(<span class="hljs-params">{ children, onSwipe }</span>) </span>{
    <span class="hljs-comment">// ... removed to improve visibility ...</span>

     useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"touchstart"</span>, handleTouchStart, { <span class="hljs-attr">passive</span>: <span class="hljs-literal">false</span> })
        <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"touchend"</span>, handleTouchEnd, { <span class="hljs-attr">passive</span>: <span class="hljs-literal">false</span> })
        <span class="hljs-comment">// ... removed to improve visibility ...</span>
      }, [handleTouchStart, handleTouchEnd])

    <span class="hljs-comment">// ... removed to improve visibility ...</span>
}
</code></pre>
<p>Now the scrolling behavior is gone and the 2048 Game looks just awesome:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/game-v2-works.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Final result - swiping works!</em></p>
<h2 id="heading-summary">🏁 Summary</h2>
<p>Today I showed you that you don't always need libraries to handle mobile gestures in React. Some simple events such as swiping can be implemented using basic React features. We just used a bunch of React hooks and wrote two simple event handlers. </p>
<p>The entire implementation has exactly 50 lines of code. I hope I inspired you to try to deal with mobile events on your own.</p>
<p>If this article helped you, please <a target="_blank" href="https://twitter.com/msokola">let me know on Twitter</a>. Educators like me often feel like we are speaking into a vacuum and nobody cares what we teach. A simple "shoutout" shows it was worth an effort and inspires me to create more content like this.</p>
<p>Please share this article on your social media. Thank you!</p>
<h2 id="heading-create-your-own-2048-game">🎥 Create Your Own 2048 Game</h2>
<p>This article is a part of my course on Udemy where I teach how to create a fully-functional 2048 Game in Next.js from scratch. </p>
<h3 id="heading-join-my-nextjs-course-on-udemyhttpswwwudemycomcourse2048-in-react-and-nextjsreferralcodeac3fd6336bab9c402106">🧑‍🎓 Join my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">Next.js course on Udemy</a></h3>
<p>Use code <strong>FREECODECAMP</strong> to enroll to get a 60% discount.</p>
<p>I believe programming should be fun and unleash creativity. You don't have to build yet another TODO list or a shopping cart. Instead, you can build something that you can show to your friends or maybe even a hiring manager!</p>
<p>PS. If you prefer to watch screencasts, then this lesson is available on Udemy for free. You can find it under the "<em>Responsive Layout and Missing Game Feature</em>" section in the lecture called "<em>Game layout and mobile swipes</em>".  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Next.js Apps to Github Pages ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I will walk you through the process of publishing a Next.js application on GitHub Pages.  What makes this guide particularly helpful is that I'll teach you how to integrate with GitHub Actions, too. This means your application will b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-next-js-app-to-github-pages/</link>
                <guid isPermaLink="false">66bc4d0460ad5c1520c16683</guid>
                
                    <category>
                        <![CDATA[ deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub Actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ github pages ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 24 Jan 2024 22:46:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Splash.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I will walk you through the process of publishing a Next.js application on GitHub Pages. </p>
<p>What makes this guide particularly helpful is that I'll teach you how to integrate with GitHub Actions, too. This means your application will be automatically deployed every time you push code to your GitHub repository.</p>
<p>We'll just focus on deployment rather than building the entire Next.js app from scratch. For our example project, we'll use one from a previous article I wrote on freeCodeCamp in my article <a target="_blank" href="https://www.freecodecamp.org/news/how-to-make-2048-game-in-react/">How to Build 2048 Game in React</a>. I recently upgraded the codebase to use React 18 and added the Next.js framework.</p>
<p>If you want to see the end result of before reading the whole article, you can <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">check it here</a>.</p>
<p>As I mentioned above, we're using a project I made in my previous tutorial – and so that you can use it here, you can find its <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">source code on Github</a>. Feel free to clone or fork this repository, and just follow the steps in the tutorial to make it with me. </p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start, make sure you know a little bit about React and Next.js. We'll also be using GitHub, so it's important to understand some basics. You don't have to be an expert, just have some basic experience with these things.</p>
<h2 id="heading-brief-introduction">Brief Introduction</h2>
<p>Today we are going to explore two new things – GitHub Actions and GitHub Pages. If you haven't heard of them, let me quickly explain:  </p>
<p><strong>GitHub Actions</strong> are like little workflows that can do tasks on your projects. It's like having a helper that automatically does things you tell it to do. You can use Actions to run tests, for quality checks, or to build your application. In our case, we're going to use these workflows to publish my <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">2048 Game</a> on GitHub Pages.</p>
<p>Now, what are <strong>GitHub Pages</strong>? Think of them like a web hosting option for developers and open source projects. You can use GitHub Pages to share your portfolios, host websites of your open-source projects, or just publish your pet projects like we're doing today.  </p>
<p>If you want to learn more, you can read more on their official websites:</p>
<ul>
<li><a target="_blank" href="https://github.com/features/actions">GitHub Actions</a></li>
<li><a target="_blank" href="https://pages.github.com/">GitHub Pages</a></li>
</ul>
<p>Now let's get our hands dirty.</p>
<h2 id="heading-step-1-activate-github-pages-for-your-repository">Step 1 – Activate GitHub Pages for Your Repository</h2>
<p>To publish our Next.js application, we have to activate GitHub Pages for our repository. Let's navigate to the Settings tab (1 in the image below), select <em>Pages</em> from the menu on the left-hand side (2), and find the dropdown menu that allows us to specify the deployment <em>Source</em> (3).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GH-Pages---Step-1a.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Project Settings</em></p>
<p>Now let's change the deployment <em>Source</em> to <em>GitHub Actions</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GH-Pages---Step-1b.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Project Settings – GitHub Pages configuration</em></p>
<p>From now on, our project has a dedicated page. We only need to create an action that will publish content there.</p>
<h2 id="heading-step-2-configure-the-nextjs-build-process">Step 2 – Configure the Next.js Build Process</h2>
<p>Before deploying the Next.js app, it's important to change the build output. By default, Next.js uses Node.js to run the application, and this is incompatible with GitHub Pages. </p>
<p>GitHub Pages is designed to host static files, which means we can publish only HTML, CSS, JavaScript (and other static files) there. So we'll need to enable static page generation in Next.js. </p>
<p>To do so, we will change the output mode to <code>export</code> inside <code>next.config.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('next').NextConfig}</span> </span>*/</span>
<span class="hljs-keyword">const</span> nextConfig = {
  <span class="hljs-attr">output</span>: <span class="hljs-string">"export"</span>,  <span class="hljs-comment">// &lt;=== enables static exports</span>
  <span class="hljs-attr">reactStrictMode</span>: <span class="hljs-literal">true</span>,
};

<span class="hljs-built_in">module</span>.exports = nextConfig;
</code></pre>
<p>Now after running <code>next build</code>, Next.js will generate an <code>out</code> folder containing static assets for our application. In the next steps, we will take this directory and upload it to GitHub Pages.</p>
<p>Side note for seasoned Next.js developers: you can use <a target="_blank" href="https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props"><code>getStaticProps</code></a> and <a target="_blank" href="https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-paths"><code>getStaticPaths</code></a> to generate static files for each page in your <code>pages</code> directory.</p>
<h2 id="heading-step-3-configure-base-path-to-fix-missing-images">Step 3 – Configure Base Path to Fix Missing Images</h2>
<p>Github publishes Pages under a sub-path of a domain and takes the project name as a sub-path. It sounds confusing, so let's take a URL to my 2048 game as an example:</p>
<pre><code class="lang-bash">https://mateuszsokola.github.io/2048-in-react/
</code></pre>
<p>As you can see, Github assigned a dedicated subdomain for me called <em>mateuszsokola</em> (after my username). But the project is published under the sub-path, which in my case is <code>/2048-in-react</code>. Unfortunately, this will lead to issues with missing images and styles. </p>
<p>By default, Next.js maps all static assets the domain. This means that the <code>favicon.ico</code> file will be resolved to <code>mateuszsokola.github.io/favicon.ico</code> instead of <code>mateuszsokola.github.io/2048-in-react/favicon.icon</code>. </p>
<p>To fix this, we can set up a path prefix by adding <code>basePath</code> inside the <code>next.config.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('next').NextConfig}</span> </span>*/</span>
<span class="hljs-keyword">const</span> nextConfig = {
  <span class="hljs-attr">basePath</span>: <span class="hljs-string">"/2048-in-react"</span>,
  <span class="hljs-attr">output</span>: <span class="hljs-string">"export"</span>,
  <span class="hljs-attr">reactStrictMode</span>: <span class="hljs-literal">true</span>,
};

<span class="hljs-built_in">module</span>.exports = nextConfig;
</code></pre>
<p>In my case, it is <code>/2048-in-react</code> since my project is called <code>2048-in-react</code>.<br><strong>Remember to include the (<code>/</code>) at beginning of the path.</strong></p>
<h2 id="heading-step-4-configure-github-actions">Step 4 – Configure Github Actions</h2>
<p>Now it's time to set up Github Actions for Next.js deployment. Reusability is a good practice so I divided the deployment into two separate actions:</p>
<ul>
<li><code>setup-node</code> action – This action is responsible for setting up Node.js and installing all dependencies. Having a standalone action for the Node.js setup enables us to reuse it for other pipelines. For example, in my 2048 Game, I have pipelines that run <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/blob/master/.github/workflows/lint.yml">code linter</a> and <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/blob/master/.github/workflows/test.yml">tests</a>. Likely you will have more than one action as well.</li>
<li><code>publish</code> action – This action handles the build process and publishes the Next.js app to GitHub Pages each time we merge code into the <code>main</code> branch.</li>
</ul>
<p>Now, you can understand why it's beneficial to split the deployment into two actions. </p>
<p>Let me begin by explaining the <code>setup-node</code> action. Here is the code:</p>
<pre><code class="lang-yml"><span class="hljs-comment"># File: .github/workflows/setup-node/action.yml</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">setup-node</span>
<span class="hljs-attr">description:</span> <span class="hljs-string">"Setup Node.js ⚙️ - Cache dependencies ⚡ - Install dependencies 🔧"</span>
<span class="hljs-attr">runs:</span>
  <span class="hljs-attr">using:</span> <span class="hljs-string">"composite"</span>
  <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Node.js</span> <span class="hljs-string">⚙️</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v4</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">node-version:</span> <span class="hljs-number">20</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Cache</span> <span class="hljs-string">dependencies</span> <span class="hljs-string">⚡</span>
      <span class="hljs-attr">id:</span> <span class="hljs-string">cache_dependencies</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/cache@v3</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">node_modules</span>
        <span class="hljs-attr">key:</span> <span class="hljs-string">node-modules-${{</span> <span class="hljs-string">hashFiles('package-lock.json')</span> <span class="hljs-string">}}</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">dependencies</span> <span class="hljs-string">🔧</span>
      <span class="hljs-attr">shell:</span> <span class="hljs-string">bash</span>
      <span class="hljs-attr">if:</span> <span class="hljs-string">steps.cache_dependencies.outputs.cache-hit</span> <span class="hljs-type">!=</span> <span class="hljs-string">'true'</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">ci</span>
</code></pre>
<p><strong>Important</strong>: Put this file in the  <code>.github/workflows/setup-node</code> directory in your project. Make sure to call the file <code>action.yml</code>.</p>
<p>What does this code do?</p>
<ul>
<li>It declares a <code>composite</code> action. The <code>composite</code> action allows you to bundle multiple workflow steps into a single action, combining multiple run commands into a single reusable action.</li>
<li>It creates a new build environment and sets up Node.js 20 there.</li>
<li>It installs npm dependencies and uses a caching mechanism to speed up this process.</li>
</ul>
<p>These are the most important parts of the <code>setup-node</code> action. Now, let's move on to the last action, which is <code>publish</code>.</p>
<pre><code class="lang-yml"><span class="hljs-comment"># File: .github/workflows/publish.yml</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">publish-to-github-pages</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">master</span>

<span class="hljs-attr">permissions:</span>
  <span class="hljs-attr">contents:</span> <span class="hljs-string">read</span>
  <span class="hljs-attr">pages:</span> <span class="hljs-string">write</span>
  <span class="hljs-attr">id-token:</span> <span class="hljs-string">write</span>

<span class="hljs-attr">concurrency:</span>
  <span class="hljs-attr">group:</span> <span class="hljs-string">"pages"</span>
  <span class="hljs-attr">cancel-in-progress:</span> <span class="hljs-literal">false</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">🛎️</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Node.js</span> <span class="hljs-string">⚙️</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Cache</span> <span class="hljs-string">dependencies</span> <span class="hljs-string">⚡</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Install</span> <span class="hljs-string">dependencies</span> <span class="hljs-string">🔧</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">./.github/workflows/setup-node</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Pages</span> <span class="hljs-string">⚙️</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/configure-pages@v4</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">static_site_generator:</span> <span class="hljs-string">next</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">with</span> <span class="hljs-string">Next.js</span> <span class="hljs-string">🏗️</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npx</span> <span class="hljs-string">next</span> <span class="hljs-string">build</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">artifact</span> <span class="hljs-string">📡</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-pages-artifact@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">./out</span>

  <span class="hljs-attr">deploy:</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">github-pages</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">${{</span> <span class="hljs-string">steps.deployment.outputs.page_url</span> <span class="hljs-string">}}</span>

    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">needs:</span> <span class="hljs-string">build</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Publish</span> <span class="hljs-string">to</span> <span class="hljs-string">GitHub</span> <span class="hljs-string">Pages</span> <span class="hljs-string">🚀</span>
        <span class="hljs-attr">id:</span> <span class="hljs-string">deployment</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/deploy-pages@v4</span>
</code></pre>
<p>Put this file in the <code>.github/workflows</code> directory in your project. You can name the file as you like – I called it <code>publish.yml</code>.</p>
<p>What does this code do?</p>
<ul>
<li>This action is executed when code is pushed or merged into the <code>main</code> branch.</li>
<li>It uses the <code>setup-node</code> action to set up the environment.</li>
<li>The action has two stages: in the first stage, the Next.js app is bundled. In the second stage, we upload the artifacts from the first stage to GitHub Pages.</li>
</ul>
<p>These are the most important aspects of the deployment pipeline. I skipped the permissions and concurrency setup since they remain unchanged for all deployments. </p>
<p>Now, your action is ready to use.</p>
<h2 id="heading-commit-and-push">Commit and Push</h2>
<p>After committing and pushing your changes to the <code>main</code> branch, GitHub will automatically initiate the deployment to GitHub Pages. </p>
<p>To inspect the process, navigate to the <em>Actions</em> tab (1 in the image below), and select the <em>publish-to-github-pages</em> action from the menu on the left hand side (2)<em>.</em> You will see a all your deployments on the screen (they are called <em>workflows</em>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GH-Pages---Summary.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Actions – Workflows responsible for publishing to GitHub Pages</em></p>
<p>Now, we need to select the first one of those workflows, and you will see a two-stage deployment. In the <em>deploy</em> stage, you can find a link to your website on GitHub Pages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GH-Pages---SummaryCI.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Project Workflow – Successful deployment</em></p>
<h2 id="heading-wrapping-up"><strong>Wrapping Up</strong></h2>
<p>Github Pages isn't sufficient for hosting websites with millions of views. But it's an excellent choice for building your portfolio or hosting a website for your open-source project. </p>
<p>Nowadays, there are many free options to host our websites, but I wanted to show you this alternative. GitHub Pages is built by developers for developers – you can consider it a developer's natural habitat. I think every developer should be familiar with it.</p>
<p>I hope this article will be a gentle push towards learning more about GitHub Actions. Feel free to experiment with different approaches and try to create your own. Every application needs to be shipped and consider this article just as a starting point.</p>
<p>Here are the resources:</p>
<ul>
<li><a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">2048 Game on Github Pages</a></li>
<li><a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/">Source code on Github</a>. It'd mean the world to me if you star ⭐ this repository.</li>
</ul>
<p>If this article helped you, please <a target="_blank" href="https://twitter.com/msokola">let me know on Twitter</a>. Educators, like me, often feel like we are speaking into a vacuum and nobody cares what we teach. A simple "shoutout" shows it was worth an effort and inspires me to work even harder to create more content like this.</p>
<p>Feel free to share this article on your social media. </p>
<p>Thank you.</p>
<p>If you wish to know more about me – My name is Matéush. I am a software engineer and digital nomad. I can say I have an extraordinary career. I lived in three different countries and worked in various environments from startups to large enterprises. </p>
<p>Recently I started to share advice on <a target="_blank" href="https://www.mateu.sh/?ref=freecodecamp.org">growing a software developer career</a>. I believe I created my blog for my younger self — a bit lost, motivated to become one of the best developers, and seeking a path into the world of “big tech”.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Tutorial – How to Build the 2048 Game in React ]]>
                </title>
                <description>
                    <![CDATA[ Today you will learn how to build your own clone of the 2048 game in React.  What makes this article unique is that we will focus on creating delightful animations. Aside from React, we will use TypeScript and we'll make some CSS transitions using LE... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-2048-game-in-react/</link>
                <guid isPermaLink="false">66bc4d0d7fa38392bfab813c</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Wed, 08 Sep 2021 01:38:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/thumb.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Today you will learn how to build your own clone of the 2048 game in React. </p>
<p>What makes this article unique is that we will focus on creating delightful animations. Aside from React, we will use TypeScript and we'll make some CSS transitions using LESS. </p>
<p>We are only going to use modern React interfaces such as hooks and the Context API. </p>
<p>This article contains a few external resources such as:</p>
<ul>
<li><a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">2048 Game (GitHub Pages)</a></li>
<li><a target="_blank" href="https://mateuszsokola.github.io/2048-animation-examples/">Animation Examples for 2048 (GitHub Pages)</a> </li>
<li><a target="_blank" href="https://github.com/mateuszsokola/2048-in-react">Source Code (GitHub)</a></li>
<li>...and a YouTube video. It took me more than a month to prepare this tutorial, so it would mean the world to me if you watch it, smash the like button, and subscribe to my channel.</li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/vI0QArPnkUc" 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>
<p>Thank you!</p>
<h2 id="heading-2048-game-rules">2048 Game Rules</h2>
<p>In this game, the player must combine tiles containing the same numbers until they reach the number 2048. The tiles can contain only integer values starting from 2, and that are a power of two, like 2, 4, 8, 16, 32, and so on. </p>
<p>Ideally, the player should reach the 2048 tile within the smallest number of steps. The board has dimension of 4 x 4 tiles, so that it can fit up to 16 tiles. If the board is full, and there is no possible move to make like merging tiles together - the game is over.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/giphy.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>While creating this tutorial I took shortcuts to focus on the game mechanics and animations. What did I get rid of?</p>
<ul>
<li>In our example, the game always creates a new tile with the number 2. But in the proper version it should generate a random number (either 2 or 4 - to make it harder to play). </li>
<li>Also, we will not handle wins and loses. You can play after you complete the number 2048, and nothing happens when the board is unsolvable - you need to click the reset button. </li>
<li>I skipped the scoring.</li>
</ul>
<p>If you want you can implement those missing features on your own. Just fork my repository and implement it on your own setup.</p>
<h2 id="heading-the-project-structure">The Project Structure</h2>
<p>The application contains the following elements:</p>
<ul>
<li>Board (component) – responsible for rendering tiles. It exposes one hook called <code>useBoard</code>.</li>
<li>Grid (component) – renders 4x4 grid.</li>
<li>Tile (component) – responsible for all animations related to the tile, and rendering the tile itself.</li>
<li>Game (component) – combines all elements above together. It includes a <code>useGame</code> hook which is responsible for enforcing the game rules and constrains.</li>
</ul>
<h2 id="heading-how-to-build-the-tile-component">How to Build the Tile Component</h2>
<p>We want to invest more time in animations, so I will start the story from the Tile component. In the end, this component is responsible for all animations in the game. </p>
<p>There are only two fairly simple animations in 2048 – tile highlighting, and sliding it across the board. We can handle those animations with CSS transitions by declaring the following styles:</p>
<pre><code class="lang-style.less">.tile {
  // ...
  transition-property: transform;
  transition-duration: 100ms;
  transform: scale(1);
}
</code></pre>
<p>At the current moment I defined only one transition that will highlight the tile when it is created or merged. We will leave it like that for now. </p>
<p>Let's consider how the Tile meta data is supposed to look, so we can easily use it. I decided to call it <code>TileMeta</code> since we don't want to have the name conflict with other entities such as the Tile component:</p>
<pre><code class="lang-typescript.tsx">type TileMeta = {
  id: number;
  position: [number, number];
  value: number;
  mergeWith?: number;
};
</code></pre>
<ul>
<li><code>id</code> – the unique identifier of the tile. It is important so that the React DOM doesn't re-render all tiles from scratch on every change. Otherwise, we would see all tiles highlighted on every action of the player.</li>
<li><code>position</code> – the position of the tile on the board. It is an array with two elements, the <code>x</code> and <code>y</code> coordinate (the possible values are <code>0</code> - <code>3</code> in both cases).</li>
<li><code>value</code> – the tile value. Only the power of two, starting from <code>2</code>.</li>
<li><code>mergeWith</code> – (optional) the id of the tile which is going to absorb the current tile. If it is present, the tile should be merged into another tile, and disappear.</li>
</ul>
<h2 id="heading-how-to-create-and-merge-tiles">How to Create and Merge Tiles</h2>
<p>We want to somehow highlight that the tile changed after the player's action. I think the best way would be changing the tile's scale to indicate that a new tile has been created or one has been changed.</p>
<pre><code class="lang-typescript.tsx">export const Tile = ({ value, position }: Props) =&gt; {
  const [scale, setScale] = useState(1);

  const prevValue = usePrevProps&lt;number&gt;(value);

  const isNew = prevCoords === undefined;
  const hasChanged = prevValue !== value;
  const shallAnimate = isNew || hasChanged;

  useEffect(() =&gt; {
    if (shallAnimate) {
      setScale(1.1);
      setTimeout(() =&gt; setScale(1), 100);
    }
  }, [shallAnimate, scale]);

  const style = {
    transform: `scale(${scale})`,
  };

  return (
    &lt;div className={`tile tile-${value}`} style={style}&gt;
      {value}
    &lt;/div&gt;
  );
};
</code></pre>
<p>To trigger the animation, we need to consider two cases:</p>
<ul>
<li>a new tile – the previous value will be <code>null</code>. </li>
<li>the tile changed the value– the previous value will be different than the current one. </li>
</ul>
<p>And the result is the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/giphy--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You might've noticed that I'm using a custom hook called <code>usePrevProps</code>. It helps to track the previous values of the component properties (props). </p>
<p>I could use references to retrieve the previous values but it would clutter up my component. I decided to extract it into a standalone hook, so the code is readable, and I can use this hook in other places.</p>
<p>If you want to use it in your project, just copy this snippet:</p>
<pre><code class="lang-typescript.ts">import { useEffect, useRef } from "react";

/**
 * `usePrevProps` stores the previous value of the prop.
 *
 * @param {K} value
 * @returns {K | undefined}
 */
export const usePrevProps = &lt;K = any&gt;(value: K) =&gt; {
  const ref = useRef&lt;K&gt;();

  useEffect(() =&gt; {
    ref.current = value;
  });

  return ref.current;
};
</code></pre>
<h2 id="heading-how-to-slide-tiles-across-the-board">How to Slide Tiles Across the Board</h2>
<p>The game will look janky without animated sliding of tiles across the board. We can easily create this animation by using CSS transitions. </p>
<p>The most convenient will be to use properties responsible for positioning, such as <code>left</code> and <code>top</code>. So we need to modify our CSS styles to look like this:</p>
<pre><code class="lang-style.less">.tile {
  position: absolute;
  // ...
  transition-property: left, top, transform;
  transition-duration: 250ms, 250ms, 100ms;
  transform: scale(1);
}
</code></pre>
<p>Once we've declared the styles, we can implement the logic responsible for changing a tile's position on the board.</p>
<pre><code class="lang-typescript.tsx">export const Tile = ({ value, position, zIndex }: Props) =&gt; {
  const [boardWidthInPixels, tileCount] = useBoard();
  // ...

  useEffect(() =&gt; {
    // ...
  }, [shallAnimate, scale]);

  const positionToPixels = (position: number) =&gt; {
    return (position / tileCount) * (boardWidthInPixels as number);
  };

  const style = {
    top: positionToPixels(position[1]),
    left: positionToPixels(position[0]),
    transform: `scale(${scale})`,
    zIndex,
  };

  // ...
};
</code></pre>
<p>As you can see, the equation in the <code>positionToPixels</code> function needs to know the position of the tile, the total amount of tiles per row and column, and the total board length in pixels (width or height – same, it is a square). The calculated value is passed down to the HTML element as an inline style.</p>
<p>Wait a minute... but what about the <code>useBoard</code> hook and <code>zIndex</code> property? </p>
<ul>
<li><code>useBoard</code> allows us to access the properties of the board within the children components without passing them down. The Tile component needs to know the width and total count of tiles to find the right spot on the board. Thanks to React Context API we can share properties across multiple layers of components without polluting their properties (props).</li>
<li><code>zIndex</code> is a CSS property that defines the order of tile on the stack. In our case it is the id of the tile. As you can see on the gif below, the tile can be stacked on each other, so the <code>zIndex</code> enabled us to specify which one will be on top.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/a.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-build-the-board">How to Build the Board</h2>
<p>Another important part of the game is the Board. The Board component is responsible for rendering the grid and tiles. </p>
<p>It seems like the Board has duplicated business logic with Tile component, but there is a small difference. The Board holds information about its size (width and height), and number of columns and rows. It's the opposite of the Tile which only knows its own position.  </p>
<pre><code class="lang-typescript.tsx">type Props = {
  tiles: TileMeta[];
  tileCountPerRow: number;
};

const Board = ({ tiles, tileCountPerRow = 4 }: Props) =&gt; {
  const containerWidth = tileTotalWidth * tileCountPerRow;
  const boardWidth = containerWidth + boardMargin;

  const tileList = tiles.map(({ id, ...restProps }) =&gt; (
    &lt;Tile key={`tile-${id}`} {...restProps} zIndex={id} /&gt;
  ));

  return (
    &lt;div className="board" style={{ width: boardWidth }}&gt;
      &lt;BoardProvider containerWidth={containerWidth} tileCountPerRow={tileCountPerRow}&gt;
        &lt;div className="tile-container"&gt;{tileList}&lt;/div&gt;
        &lt;Grid /&gt;
      &lt;/BoardProvider&gt;
    &lt;/div&gt;
  );
};
</code></pre>
<p>The Board component uses the <code>BoardProvider</code> to distribute the width of the tile container and amount of tiles per row and column to all tiles and the grid component. </p>
<pre><code class="lang-typescript.tsx">const BoardContext = React.createContext({
  containerWidth: 0,
  tileCountPerRow: 4,
});

type Props = {
  containerWidth: number;
  tileCountPerRow: number;
  children: any;
};

const BoardProvider = ({
  children,
  containerWidth = 0,
  tileCountPerRow = 4,
}: Props) =&gt; {
  return (
    &lt;BoardContext.Provider value={{ containerWidth, tileCountPerRow }}&gt;
      {children}
    &lt;/BoardContext.Provider&gt;
  );
};
</code></pre>
<p>The <code>BoardProvider</code> uses the React Context API to propagate properties down to every child. If any component needs to use any value available on the provider it can retrieve it by calling the <code>useBoard</code> hook. </p>
<p>I am going to skip this topic since I spoke more about it in my <a target="_blank" href="https://youtu.be/H9Tx5SqWX9o">video on Feature Toggles in React</a>. If you wish to learn more about them you can watch it.</p>
<pre><code class="lang-typescript.tsx">const useBoard = () =&gt; {
  const { containerWidth, tileCount } = useContext(BoardContext);

  return [containerWidth, tileCount] as [number, number];
};
</code></pre>
<h2 id="heading-how-to-build-the-game-component">How to Build the Game Component</h2>
<p>Now we can specify the rules of game, and expose the interface to play the game. I am going to start with the navigation since it will help you understand why the game logic is implemented that way. </p>
<pre><code class="lang-typescript.tsx">import { useThrottledCallback } from "use-debounce";

const Game = () =&gt; {
  const [tiles, moveLeft, moveRight, moveUp, moveDown] = useGame();

  const handleKeyDown = (e: KeyboardEvent) =&gt; {
      // disables page scrolling with keyboard arrows
    e.preventDefault();

    switch (e.code) {
      case "ArrowLeft":
        moveLeft();
        break;
      case "ArrowRight":
        moveRight();
        break;
      case "ArrowUp":
        moveUp();
        break;
      case "ArrowDown":
        moveDown();
        break;
    }
  };

  // protects the reducer from being flooded with events.
  const throttledHandleKeyDown = useThrottledCallback(
    handleKeyDown,
    animationDuration,
    { leading: true, trailing: false }
  );

  useEffect(() =&gt; {
    window.addEventListener("keydown", throttledHandleKeyDown);

    return () =&gt; {
      window.removeEventListener("keydown", throttledHandleKeyDown);
    };
  }, [throttledHandleKeyDown]);

  return &lt;Board tiles={tiles} tileCountPerRow={4} /&gt;;
};
</code></pre>
<p>As you can see, the game logic will be handled by the <code>useGame</code> hook that exposes the following properties and methods:</p>
<ul>
<li><code>tiles</code> – an array of tiles available on the board. It uses the <code>TileMeta</code> type described above.</li>
<li><code>moveLeft</code> – a function that slides all tiles to the left side of the board.</li>
<li><code>moveRight</code> – a function that slides all tiles to the right side of the board.</li>
<li><code>moveUp</code> – a function that slides all tiles to the top of the board.</li>
<li><code>moveDown</code> – a function that slides all tiles to the bottom of the board.</li>
</ul>
<p>We use the <code>throttledHandleKeyDown</code> callback to prevent players from flooding the game with tons of moves at the same time. Basically, the player needs to wait until the animation is complete before they can trigger another move. </p>
<p>This mechanism is called throttling. I decided to use the <code>useThrottledCallback</code> hook from the <code>use-debounce</code> package. </p>
<h2 id="heading-how-to-use-the-usegame-hook">How to Use the useGame Hook</h2>
<p>I mentioned above that the Game component will be handling the rules of the game as well. We are going to extract the game logic into a hook rather than writing it directly onto the component (since we don't want to clutter the code).</p>
<p>The useGame hook is based on the <code>useReducer</code> hook which is a built-in hook within React. I will start by defining the shape of the reducer's state. </p>
<pre><code class="lang-typescript.tsx">type TileMap = { 
  [id: number]: TileMeta;
}

type State = {
  tiles: TileMap;
  inMotion: boolean;
  hasChanged: boolean;
  byIds: number[];
};
</code></pre>
<p>The state contains the following fields:</p>
<ul>
<li><code>tiles</code> – a hash table responsible for storing tiles. The hash table makes it easy to lookup entries by their keys, so it is a perfect match for us since we want to find tiles by their ids.</li>
<li><code>byIds</code> – an array containing all ids in the expected order (that is, ascending). We must keep the right order of tiles, so React doesn't re-render the whole board every time we change the state.</li>
<li><code>hasChange</code> – keeps track of tile changes. If nothing has changed the new tile will not be generated.</li>
<li><code>inMotion</code> – determines if tiles are still moving. If they are, the new tile will not be generated until the motion is completed.</li>
</ul>
<h3 id="heading-actions">Actions</h3>
<p><code>useReducer</code> requires to specify the actions that are supported by this reducer. </p>
<pre><code class="lang-typescript.tsx">type Action =
  | { type: "CREATE_TILE"; tile: TileMeta }
  | { type: "UPDATE_TILE"; tile: TileMeta }
  | { type: "MERGE_TILE"; source: TileMeta; destination: TileMeta }
  | { type: "START_MOVE" }
  | { type: "END_MOVE" };
</code></pre>
<p>What are those actions responsible for?</p>
<ul>
<li><code>CREATE_TILE</code> – creates a new tile, and appends it into the <code>tiles</code> hash table. It changes the <code>hasChange</code> flag to <code>false</code> since this action is always triggered when a new tile is appended to the board. </li>
<li><code>UPDATE_TILE</code> – updates an existing tile. It doesn't modify the id which is important to keep the animations working. We will use it to reposition the tile and change its value (during merges). Also, it changes the <code>hasChange</code> flag to <code>true</code>.</li>
<li><code>MERGE_TILE</code> – merges a source tile into a destination tile. After this operation, the destination tile will change its value (the value of the source tile will be added into it). And it will remove the source tile from the <code>tiles</code> table and <code>byIds</code> array.</li>
<li><code>START_MOVE</code> – tells the reducer it should expect multiple actions, so it must wait until all animations are complete before it will be able to generate a new tile.</li>
<li><code>END_MOVE</code> – tells the reducer all actions were completed, and it can safely create a new tile.</li>
</ul>
<p>If you want you can write the logic for this reducer on your own or copy mine:</p>
<pre><code class="lang-typescript.tsx">type TileMap = { 
  [id: number]: TileMeta;
}

type State = {
  tiles: TileMap;
  inMotion: boolean;
  hasChanged: boolean;
  byIds: number[];
};

type Action =
  | { type: "CREATE_TILE"; tile: TileMeta }
  | { type: "UPDATE_TILE"; tile: TileMeta }
  | { type: "MERGE_TILE"; source: TileMeta; destination: TileMeta }
  | { type: "START_MOVE" }
  | { type: "END_MOVE" };

const initialState: State = {
  tiles: {},
  byIds: [],
  hasChanged: false,
  inMotion: false,
};

const GameReducer = (state: State, action: Action) =&gt; {
  switch (action.type) {
    case "CREATE_TILE":
      return {
        ...state,
        tiles: {
          ...state.tiles,
          [action.tile.id]: action.tile,
        },
        byIds: [...state.byIds, action.tile.id],
        hasChanged: false,
      };
    case "UPDATE_TILE":
      return {
        ...state,
        tiles: {
          ...state.tiles,
          [action.tile.id]: action.tile,
        },
        hasChanged: true,
      };
    case "MERGE_TILE":
      const {
        [action.source.id]: source,
        [action.destination.id]: destination,
        ...restTiles
      } = state.tiles;
      return {
        ...state,
        tiles: {
          ...restTiles,
          [action.destination.id]: {
            id: action.destination.id,
            value: action.source.value + action.destination.value,
            position: action.destination.position,
          },
        },
        byIds: state.byIds.filter((id) =&gt; id !== action.source.id),
        hasChanged: true,
      };
    case "START_MOVE":
      return {
        ...state,
        inMotion: true,
      };
    case "END_MOVE":
      return {
        ...state,
        inMotion: false,
      };
    default:
      return state;
  }
};
</code></pre>
<p>If you don't understand why we defined those actions, don't worry – now we are going to implement a hook which will hopefully shed some light on it.</p>
<h3 id="heading-how-to-implement-the-hook">How to Implement the Hook</h3>
<p>Let's look into the function which is responsible for a player's moves. We will focus on the move left only since the other ones are almost the same.</p>
<pre><code class="lang-typescript.tsx">  const moveLeftFactory = () =&gt; {
    const retrieveTileIdsByRow = (rowIndex: number) =&gt; {
      const tileMap = retrieveTileMap();

      const tileIdsInRow = [
        tileMap[tileIndex * tileCount + 0],
        tileMap[tileIndex * tileCount + 1],
        tileMap[tileIndex * tileCount + 2],
        tileMap[tileIndex * tileCount + 3],
      ];

      const nonEmptyTiles = tileIdsInRow.filter((id) =&gt; id !== 0);
      return nonEmptyTiles;
    };

    const calculateFirstFreeIndex = (
      tileIndex: number,
      tileInRowIndex: number,
      mergedCount: number,
      _: number
    ) =&gt; {
      return tileIndex * tileCount + tileInRowIndex - mergedCount;
    };

    return move.bind(this, retrieveTileIdsByRow, calculateFirstFreeIndex);
  };

  const moveLeft = moveLeftFactory();
</code></pre>
<p>As you can see, I decided to bind two callbacks to the <code>move</code> function. This technique is called the inversion of control – so the consumer of the function will be able to inject their own values into the executed function. </p>
<p>If you don't know how <code>bind</code> works you should learn about it because it is a very common question on job interviews. </p>
<p>The first callback called <code>retrieveTileIdsByRow</code> is responsible of finding all non-empty tiles available in a row (for horizontal moves – left or right). If the player does the vertical (up or down) moves we will look for all tiles in a column.</p>
<p>The second callback called <code>calculateFirstFreeIndex</code> finds the closest position to the board's border based on the given parameters such as tile index, index of the tile in row or column, number of merged tiles, and the maximum possible index. </p>
<p>Now we are going to look into the business logic of the <code>move</code> function. I've explained the code of this function in the comments. The algorithm might be a bit complex, and I believe It will be easier to understand it if I document the code line by line:</p>
<pre><code class="lang-typescript.tsx">  type RetrieveTileIdsByRowOrColumnCallback = (tileIndex: number) =&gt; number[];

  type CalculateTileIndex = (
    tileIndex: number,
    tileInRowIndex: number,
    mergedCount: number,
    maxIndexInRow: number
  ) =&gt; number;

  const move = (
    retrieveTileIdsByRowOrColumn: RetrieveTileIdsByRowOrColumnCallback,
    calculateFirstFreeIndex: CalculateTileIndex
  ) =&gt; {
    // new tiles cannot be created during motion.
    dispatch({ type: "START_MOVE" });

    const maxIndex = tileCount - 1;

    // iterates through every row or column (depends on move kind - vertical or horizontal).
    for (let tileIndex = 0; tileIndex &lt; tileCount; tileIndex += 1) {
      // retrieves tiles in the row or column.
      const availableTileIds = retrieveTileIdsByRowOrColumn(tileIndex);

      // previousTile is used to determine if tile can be merged with the current tile.
      let previousTile: TileMeta | undefined;
      // mergeCount helps to fill gaps created by tile merges - two tiles become one.
      let mergedTilesCount = 0;

      // interate through available tiles.
      availableTileIds.forEach((tileId, nonEmptyTileIndex) =&gt; {
        const currentTile = tiles[tileId];

        // if previous tile has the same value as the current one they should be merged together.
        if (
          previousTile !== undefined &amp;&amp;
          previousTile.value === currentTile.value
        ) {
          const tile = {
            ...currentTile,
            position: previousTile.position,
            mergeWith: previousTile.id,
          } as TileMeta;

          // delays the merge by 250ms, so the sliding animation can be completed.
          throttledMergeTile(tile, previousTile);
          // previous tile must be cleared as a single tile can be merged only once per move.
          previousTile = undefined;
          // increment the merged counter to correct position for the consecutive tiles to get rid of gaps
          mergedTilesCount += 1;

          return updateTile(tile);
        }

        // else - previous and current tiles are different - move the tile to the first free space.
        const tile = {
          ...currentTile,
          position: indexToPosition(
            calculateFirstFreeIndex(
              tileIndex,
              nonEmptyTileIndex,
              mergedTilesCount,
              maxIndex
            )
          ),
        } as TileMeta;

        // previous tile becomes the current tile to check if the next tile can be merged with this one.
        previousTile = tile;

        // only if tile has changed its position will it be updated
        if (didTileMove(currentTile, tile)) {
          return updateTile(tile);
        }
      });
    }

    // wait until the end of all animations.
    setTimeout(() =&gt; dispatch({ type: "END_MOVE" }), animationDuration);
  };
</code></pre>
<p>The complete code of this hook has more than 400 lines of code, so instead of pasting it here I decided to keep it on GitHub – so please <a target="_blank" href="https://github.com/mateuszsokola/2048-in-react/blob/master/src/components/Game/hooks/useGame/useGame.ts">review the complete code there</a>.</p>
<h2 id="heading-homework">Homework</h2>
<p>I mentioned above that a few features are missing. If you want to understand the code in depth, you could fork my repository, and implement the following features:</p>
<ul>
<li>score – you can define your own algorithm.</li>
<li>support wins and loses.</li>
<li>for new tile generation, pick a random tile value - either 2 or 4. The 4 shouldn't appear fewer than 5% of the times.</li>
</ul>
<p>If you want me to review your code you can invite me to your pull request on GitHub - my username is mateuszsokola. Maybe I will record a video about how I review your code.</p>
<h2 id="heading-summary">Summary</h2>
<p>I hope you enjoyed my tutorial. This time I decided to focus on the essence of the topic rather than building basic React and CSS, so I skipped those basic parts. I believe it makes this article easier to digest. </p>
<p>Any feedback or questions? <a target="_blank" href="https://twitter.com/msokola">Shout at me on twitter</a>!</p>
<p>If you found this article helpful please share it, so more developers can learn from it. Occasionally I <a target="_blank" href="https://www.youtube.com/channel/UCJV16_5c4A0amyBZSI4yP6A">publish videos on my YouTube channel</a>, and it would be great if you subscribe to my channel, hit the like button, and drop a comment under your favourite video.</p>
<p>Stay tuned!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
