<?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[ Chris Blakely - 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[ Chris Blakely - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:29:56 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/chrisblakely01/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Debug Coding Problems When Building Your Own Projects ]]>
                </title>
                <description>
                    <![CDATA[ Ah, the joy of coding! There you are, cruising through your project, when suddenly – bam! – you hit a bug. It's like hitting a wall in a maze. But fear not, fellow coder, for I bring you the trusty map to navigate the treacherous bug-infested waters ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/debug-coding-problems-in-your-projects/</link>
                <guid isPermaLink="false">66c8c8d0fe21816c4cb75d13</guid>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ logging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Tue, 20 Feb 2024 21:47:09 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/08/pexels-pixabay-144243--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ah, the joy of coding! There you are, cruising through your project, when suddenly – bam! – you hit a bug. It's like hitting a wall in a maze.</p>
<p>But fear not, fellow coder, for I bring you the trusty map to navigate the treacherous bug-infested waters of programming. Whether you're a self-learner aiming to land that dream job in tech or just tinkering for fun, here's how to become a debugging ninja.</p>
<h2 id="heading-look-for-errors-in-your-ide">Look for Errors in Your IDE</h2>
<p>Your Integrated Development Environment (IDE) isn't just a fancy text editor – it's your first line of defense against bugs. </p>
<p>TypeScript, for example, is like that friend who points out the pothole you're about to step into – it helps catch errors early with its type-checking prowess. </p>
<p>Imagine you accidentally try to add a number to a string. TypeScript waves a big red flag, saving you from a facepalm moment later. It's one of the many reasons we adore TS.</p>
<p><strong>Example</strong>: You declare <code>let age: number = 'twenty';</code>. TypeScript will frown upon this, telling you that 'twenty' is not a number. It's like having a guardian angel for your code.</p>
<h2 id="heading-try-and-isolate-the-area">Try and Isolate the Area</h2>
<p>Before you start pulling out your hair, try to play detective and isolate where the crime scene is. </p>
<p>Is the bug lurking in the backend, hiding in the frontend, conspiring in the database, or chilling in the infrastructure? </p>
<p>When you're working locally, it's usually one of the first three suspects. And here's a hot tip: the network tab in your browser's developer tools is like your police scanner, helping you pinpoint the location of the distress call.</p>
<p><strong>Example</strong>: Let's say you send out a request to GET /users and it returns a 500 status. That's the server telling you, "Mate, I've got problems." It's a backend issue. But if the call comes back with a 200 status and your UI is still playing hide and seek with the data, then the bug's hosting a party in your frontend. The network tab just handed you the address.</p>
<p>By narrowing down the location of your issue, you can focus your debugging efforts more efficiently. It's like knowing whether to raid the castle, the dragon's lair, or the dark forest. Happy hunting!</p>
<h2 id="heading-look-for-errors-in-the-browser-console">Look for Errors in the Browser Console</h2>
<p>The browser console is your Sherlock Holmes magnifying glass for web projects. It uncovers clues hidden in plain sight. The console tab, on the other hand, is like tracking where the villain has been, helping you spot those pesky code misfires. </p>
<p><strong>Example</strong>: Your React app isn't fetching data. A quick peek in the console tab shows an "undefined" error, and a line number. This is where your problem is at. Elementary, my dear Watson!</p>
<h2 id="heading-add-consolelog-to-different-functions">Add <code>console.log()</code> to Different Functions</h2>
<p>Ah, the humble <code>console.log()</code>, the print statement that could. When in doubt, log it out. It's like dropping breadcrumbs through your code to see how far Little Red Riding Hood gets before she meets the Big Bad Bug.</p>
<p><strong>Example</strong>: Unsure if your function is receiving the expected data? <code>console.log('Data:', data)</code> at the start of the function. No data? Now you know where the problem starts.</p>
<h2 id="heading-use-try-catch-blocks">Use Try-Catch Blocks</h2>
<p>Try-catch blocks are your safety net, allowing your code to perform daring feats without crashing your app. They let you gracefully handle errors by catching them before they wreak havoc. They also let you specify your own custom error messages for a given block of code, helping you to find the problem area.</p>
<p><strong>Example</strong>: Wrap your API call in a try-catch. If the call fails, the catch block catches the error, allowing you to console.log it or display a friendly message to the user. </p>
<p>Heres what a try catch block looks like in JS:</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayUsers</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> users = getUsers();
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"oh crap"</span>);
    }
  }
</code></pre>
<h2 id="heading-search-google-or-use-chatgpt-to-help-with-error-messages">Search Google or Use ChatGPT to Help With Error Messages</h2>
<p>Stuck on an error message? Google and ChatGPT are your library and librarian. Just copy and paste the error into the search bar and watch a plethora of solutions unfold. It's like asking the hive mind: someone, somewhere, has had your problem before.</p>
<p><strong>Example</strong>: Getting a "TypeError: Cannot read property 'map' of undefined"? A quick search reveals you might be trying to use <code>.map()</code> on something that's not an array. Oops!</p>
<h2 id="heading-test-often">Test Often</h2>
<p>The mantra "test early, test often" will save you heaps of time. By testing small bits of code as you go, you catch bugs early, when they're easier to squash. It's like cleaning as you cook– it makes the final cleanup so much easier.</p>
<p><strong>Example</strong>: Just added a new feature? Test it out before moving on. Does it work as expected? Great! No? Time to debug while the code is still fresh in your mind.</p>
<h2 id="heading-try-a-different-approach">Try a Different Approach</h2>
<p>If you're banging your head against the wall with a problem, maybe it's time to climb over it instead. Don't get too attached to your code. Be willing to refactor or even start from scratch if it means a cleaner, more elegant solution.</p>
<p><strong>Example</strong>: If your code is more tangled than a bowl of spaghetti, stepping back and rethinking your approach might reveal a simpler, more efficient path.</p>
<p>Debugging is part art, part science, and entirely a test of patience. But with these strategies in your toolkit, you'll be squashing bugs with the best of them. Happy coding, and may your bug hunts be short and your code be clean!</p>
<h2 id="heading-real-life-scenario">Real Life Scenario</h2>
<p>Let's take real life scenario. I have a React, Node, Postgres app that displays users in the browser. The code, as far as I know, should be working but I'm not seeing the users displayed on the frontend.</p>
<h3 id="heading-step-1-check-the-console">Step 1 – Check the Console</h3>
<p>Let's have a nosey at the Chrome dev tools console and see what's going on. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/step1.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>"Look ma, errors!"</em></p>
<p>Ah, the plot thickens in the saga of "Why isn't this thing working?". Let's dive into the drama unfolding in your console and break down the breadcrumbs left behind by our mischievous friend, the bug.</p>
<p>First up, we have our leading clue: <code>GET http://localhost:3000/api/users 500 (Internal Server Error)</code>. This line is the equivalent of a scream in the night in our detective story. It tells us that our backend is in distress, possibly tied to a nefarious SQL query or a rogue piece of logic in our API route. </p>
<p>The server's cry for help is loud and clear: "Internal Server Error." Classic move by the backend, really.</p>
<p>Now, our supporting cast makes their entrance with <code>ResponseError: Response returned an error code</code>. This is the big reveal. The issue isn't just a server having a bad day – it's a ResponseError caught red-handed by <code>UsersApi.request</code>, and even tells us where the error line is (UserApi.ts:83).</p>
<h3 id="heading-step-2-check-the-backend-terminal">Step 2 – Check the backend Terminal</h3>
<p>Our journey into investigating the bug has brought us to the backend, where we are greeted with this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/step2.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you see this and your first instinct is to run away and hide, don't worry – that was mine too. But fear not! There are plenty of clues that point us to the issue. </p>
<p>When a backend error occurs, this is what's known as a <strong>stack trace</strong> – basically all the errors, info, line numbers, and so on that the compiler encountered in one big block of text. Thanks compiler!  </p>
<p>What we do here is look for key words, recognisable files, or anything that's readable by humans. Did you spot anything? Let's dive deeper:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/step2-1.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Digging deeper into the errors</em></p>
<p>The highlighted parts in <strong>yellow</strong>, indicate that there was an error in <code>userController.ts</code>, specifically at <code>getAllUsers()</code> function. If we read further, the highlighted parts in <strong>red point</strong>  us to the error message:</p>
<pre><code class="lang-bash">Authentication failed against database server at `dpg-cn9kr28l6cac73a1a7eg-a.frankfurt-postgres.render.com`, 
the provided database credentials <span class="hljs-keyword">for</span> `dmin` are not valid.\n\nPlease make sure to provide valid database credentials <span class="hljs-keyword">for</span> the database server
</code></pre>
<p>Hurray! Now we know the error. We have spelled "admin" incorrectly in our database connection string, meaning the connection failed. Doh! After we fix this, the error is resolved:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/step4.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Error resolved</em></p>
<h3 id="heading-step-3-verify-the-fix">Step 3: Verify the Fix</h3>
<p>Now we've added a fix, we can verify by checking the browser to see if everything's working. In this case, checking the UI is enough to verify, but for more complex flows you can get that the API is returning the correct status code (in this case, 200)</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this article has shed some light on how you can debug your projects. </p>
<p>If you are looking for more debugging insights, and real industry level projects to build, you can check out by YouTube where we build and deploy full stack applications using React, Node, and some other cool tech. Hope to see you there!  </p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/undefined" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get the Most of Video Coding Tutorials ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever spent hours watching a coding tutorial, only to get to the end and feel like you haven't learned very much?  We've all been there, and it can be a frustrating experience when learning to code.  In this article, I will show you some of t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-the-most-out-of-video-coding-tutorials/</link>
                <guid isPermaLink="false">66c8c8eefe21816c4cb75d1d</guid>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Fri, 16 Feb 2024 00:50:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/pexels-olia-danilevich-4974915.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever spent hours watching a coding tutorial, only to get to the end and feel like you haven't learned very much? </p>
<p>We've all been there, and it can be a frustrating experience when learning to code. </p>
<p>In this article, I will show you some of the best techniques you can use to get the most out of any video tutorial and maximize your learning.</p>
<h2 id="heading-code-along">🎮 Code Along</h2>
<p>This is a great way to practice the actual typing of code, and you'll build muscle memory as you do. Eventually things like creating functions, new files, and so on will become second nature. It also helps to drive home the concepts you're learning.</p>
<p>Imagine playing a video game where you're just watching the hero battle dragons without jumping into the fray yourself. Sounds boring, right? And you wouldn't get any better at fighting the dragons.</p>
<p>That's exactly why you should <em>code along</em> with tutorials instead of passively watching them. Open your IDE, type out the code, and run it. See those errors and successes in real time? They’re your battle scars and medals. </p>
<h3 id="heading-example">Example:</h3>
<p>When the tutorial says, "Let's build a to-do list," don't just nod along. Build it as they do, line by line. If they add a feature to check off completed tasks, jump in and code that checkbox. It's like following a recipe – you wouldn't just read it and expect a cake to appear. </p>
<h2 id="heading-make-a-note-of-common-functionality">📝 Make a Note of Common Functionality</h2>
<p>Coding is not just about learning syntax – it's about learning how to recognize patterns. Many web apps share common functionalities. Authentication, CRUD operations (Create, Read, Update, Delete), and API calls are your bread and butter.</p>
<h3 id="heading-example-1">Example:</h3>
<p>In my <a target="_blank" href="https://www.youtube.com/channel/UC-Zcse8tC53G34Uo4kzLeAg">full-stack project videos on YouTube</a>, I show you how to implement a lot of common web app features such as authentication, CRUD operations, sorting, filtering, and more. If you take a note on how and when to use these features, you'll be able to refer back to this when you need these features in your future projects.</p>
<h2 id="heading-watch-a-section-and-see-if-you-can-redo-that-section-yourself">🔄 Watch a Section, and See If You Can Redo That Section Yourself</h2>
<p>This is where the magic happens. After watching a segment, take a deep breath, and try to replicate what you just learned without peeking. </p>
<p>It's like trying to draw a map of a dungeon after walking through it once. Don’t worry if you miss a turn – the goal is to etch those coding pathways into your brain. Remember: repetition is key for learning coding concepts.</p>
<h3 id="heading-example-2">Example:</h3>
<p>If the tutorial just showed how to add a feature to sort tasks by priority, close the video and see if you can implement it again from scratch. It's okay to struggle. That's when you know you're learning. You can always refer back to the video if you get stuck and then try again.</p>
<h2 id="heading-see-if-you-can-do-the-next-section-yourself">🚀 See If You Can Do the Next Section Yourself</h2>
<p>Feeling bold? Try to predict and code the next feature before the tutorial shows you how. It’s like choosing your own adventure in a storybook. This not only tests your understanding but also boosts your problem-solving skills.</p>
<h3 id="heading-example-3">Example:</h3>
<p>The tutorial plans to add a feature to filter tasks? Take a stab at it before hitting play. Whether you nail it or not, comparing your approach to the tutorial's solution offers incredible insights. </p>
<h2 id="heading-pause-and-add-your-own-little-bits">⏸ Pause and Add Your Own Little Bits</h2>
<p>Who says you have to stick to the script? Toss in your own mini-features or tweaks. If the tutorial’s app is as plain as a potato, why not spice it up with some CSS magic? Or add a feature that you think would be useful?</p>
<h3 id="heading-example-4">Example:</h3>
<p>Building that to-do list but it's all text? Add emojis for tasks! 🎉 A task about calling your grandma? Slap a heart emoji next to it. It’s your world – have fun decorating it. </p>
<h2 id="heading-extend-the-tutorial-with-your-own-features">🌟 Extend the Tutorial with Your Own Features</h2>
<p>This is one of my favourite ways to learn, as it's not as daunting as starting from a blank slate. </p>
<p>Once you've followed the tutorial to the end, don't stop there. Think of it as the base game, and now you're adding DLCs (Downloadable Content). This is your chance to get creative and make the project truly yours. </p>
<h3 id="heading-example-5">Example:</h3>
<p>Got that to-do list working? Great! How about adding a feature to share tasks with friends or sync it across devices? The sky's the limit. </p>
<h2 id="heading-take-lots-of-breaks">🏖 Take Lots of Breaks</h2>
<p>Ever noticed how ideas sometimes hit you when you're away from the computer, maybe in the shower or taking a walk? That's your brain processing in the background. </p>
<p>Coding marathons can lead to burnout, so remember to take breaks. Stretch, hydrate, or do a quick dance-off. Your brain (and body) will thank you. </p>
<h3 id="heading-example-6">Example:</h3>
<p>After coding a new feature, step away for a bit. Try taking a walk, or working on another non-coding project. You might come back with a fresh perspective or a new idea to implement. It’s like letting your game character rest at an inn before the next big quest. 😉</p>
<h2 id="heading-conclusion">🔍 Conclusion</h2>
<p>If you're eager to put these techniques into practice, feel free to visit my YouTube channel. There, I tackle enterprise-level projects, unravelling the how, the what, and the why behind each line of code. Drop by and say hello!</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/undefined" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ MERN Stack Roadmap – How to Learn MERN and Become a Full-Stack Developer ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever wondered how modern web applications are built? How you can learn and master the technologies that you can use to build your own full stack projects from scratch? In this handbook, I'm going to introduce you to the MERN stack, a widely-... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mern-stack-roadmap-what-you-need-to-know-to-build-full-stack-apps/</link>
                <guid isPermaLink="false">66c8c8f7fe21816c4cb75d21</guid>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Thu, 04 Jan 2024 00:57:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Copy-of-mern-stack-hotel-booking-website--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever wondered how modern web applications are built? How you can learn and master the technologies that you can use to build your own full stack projects from scratch?</p>
<p>In this handbook, I'm going to introduce you to the MERN stack, a widely-used technology stack embraced by many leading companies. I'll guide you through 7 essential steps to start learning these technologies on your own. </p>
<p>By the time you finish reading, you'll have a solid understanding of what the MERN stack entails, its component technologies, and various resources for learning. You'll also have 10 project ideas that you can develop and showcase in your portfolio.</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-the-mern-stack">What is the MERN stack?</a></li>
<li><a class="post-section-overview" href="#heading-the-mern-stack-roadmap">The MERN Stack Roadmap</a><ul>
<li><a class="post-section-overview" href="#heading-step-1-learn-the-right-amount-of-html-javascript-and-css">STEP 1: Learn the right amount of HTML, JavaScript, and CSS</a></li>
<li><a class="post-section-overview" href="#heading-step-2-get-familiar-with-react">STEP 2: Get familiar with React</a></li>
<li><a class="post-section-overview" href="#heading-step-3-understand-rest-apis-and-how-a-backend-server-works-using-expressnode">STEP 3: Understand REST API's and how a backend server works using Express/Node</a></li>
<li><a class="post-section-overview" href="#heading-step-4-storing-data-with-mongodb-and-mongoose">STEP 4: Storing data with MongoDB and Mongoose</a></li>
<li><a class="post-section-overview" href="#heading-step-5-writing-tests">STEP 5: Writing tests</a></li>
<li><a class="post-section-overview" href="#heading-step-6-using-git">STEP 6: Using Git</a></li>
<li><a class="post-section-overview" href="#heading-step-7-deployments">STEP 7: Deployments</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-top-resources-to-learn-the-mern-stack">Top Resources to learn the MERN Stack</a></li>
<li><a class="post-section-overview" href="#heading-10-project-ideas-you-can-try-today">10 project ideas you can try today</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up-the-mern-stack-journey">Wrapping up the MERN stack journey</a></li>
</ol>
<h2 id="heading-what-is-the-mern-stack">What is the MERN stack?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/MERN-Stack-wallpaper-gigapixel-hq-scale-6_00x.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The MERN stack, comprising MongoDB, Express.js, React, and Node.js, is a cohesive set of technologies used for building efficient and scalable web applications. </p>
<p>Its popularity stems from the seamless integration of each component: MongoDB's flexible data handling, Express.js's efficient server-side networking, React's dynamic user interfaces, and Node.js's powerful back-end runtime environment. </p>
<p>For beginners, the MERN stack is a smart choice because it uses JavaScript across all layers, simplifying the learning curve. This uniformity, coupled with a strong community and ample learning resources, makes it an accessible and practical toolkit for anyone looking to dive into full-stack development.</p>
<p>The MERN stack is also heavily utilized in the industry, favored by startups and large enterprises alike for its efficiency and the robust, modern web applications it can produce. This industry adoption not only validates its effectiveness but also opens up numerous career opportunities for those skilled in these technologies.</p>
<p>Let's look at a brief overview of what each part of the MERN Stack looks like:</p>
<h3 id="heading-frontend-react">Frontend (React)</h3>
<p>The frontend of a website is like the dining area of a restaurant. It's everything you see and interact with directly on a website – the layout, design, buttons, and text.  </p>
<p><strong>Example</strong>: When you visit a website and see a beautiful homepage, interact with menus, or fill out forms, you're experiencing the frontend.</p>
<h3 id="heading-backend-nodejs">Backend (Node.js)</h3>
<p>The backend is like the kitchen in a restaurant. It's where all the behind-the-scenes work happens. It includes the server, applications, and databases that work together to process the information you see on the frontend.  </p>
<p><strong>Example</strong>: When you order food (submit a form on the website), the kitchen (backend) processes the order (the data) and prepares your meal (the information or service you requested).</p>
<h3 id="heading-database-mongodb">Database (MongoDB)</h3>
<p>A database in web development is similar to a restaurant’s pantry or storage where all the ingredients (data) are kept. It stores and manages all the information needed by the website, like user profiles, content, and other data.  </p>
<p><strong>Example</strong>: In an online store, the database stores product information, prices, user reviews, and customer details.</p>
<h3 id="heading-rest-apis-express">REST APIs (Express)</h3>
<p>REST APIs are like the waiters in a restaurant. They are the messengers or go-betweens for the frontend and backend. They take requests (like orders) from the frontend (customer), fetch or update data in the backend (kitchen), and then return responses (prepared orders). </p>
<p>The terms POST, PUT, DELETE, and GET are types of requests used in REST APIs:</p>
<ul>
<li><strong>POST</strong>: Used to create new data. Like placing a new order in the restaurant.</li>
<li><strong>PUT</strong>: Used to update existing data. Similar to changing an order you've already placed.</li>
<li><strong>DELETE</strong>: Used to remove data. Like cancelling an order.</li>
<li><strong>GET</strong>: Used to retrieve data. Comparable to asking about the menu or checking the status of your order.</li>
</ul>
<h2 id="heading-the-mern-stack-roadmap">The MERN Stack Roadmap</h2>
<h3 id="heading-step-1-learn-the-right-amount-of-html-javascript-and-css">STEP 1: Learn the right amount of HTML, JavaScript, and CSS</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/b59a78e2ed76c705f3c0dcb300f3f222aefdcd99-gigapixel-hq-scale-6_00x.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The MERN stack uses JavaScript heavily, so its a natural first step to learn. In this section you will look at the main things you will use day-to-day when creating full-stack MERN apps. </p>
<p>Understanding JavaScript is like knowing the right amount of ingredients needed for a recipe. You don't need to master everything at once, just the essential ingredients that make your particular dish (or your web project) come to life.</p>
<h3 id="heading-variables">Variables</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/javascript-variables-beginners-guide/">Variables in JavaScript</a> are like labelled jars in your kitchen. You can store things in them (like numbers, text) and use these jars later in your cooking (or coding).</p>
<p><strong>Example</strong>: A variable storing the user's name, so you can use it later to say "Hello, [Name]!"</p>
<h3 id="heading-functions">Functions</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/javascript-functions-and-scope/">Functions</a> are like recipes in a cookbook. They are sets of instructions that perform a specific task. You can reuse these recipes whenever you need to perform that task again.</p>
<p><strong>Example</strong>: A function that calculates the total price of items in a shopping cart.</p>
<h3 id="heading-objects-amp-arrays">Objects &amp; Arrays</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/javascript-basics-strings-arrays-objects/">Objects</a> are like information cards holding details about something (like a contact card), and arrays are like lists.  </p>
<p><strong>Example of an Object</strong>: A card holding a user's information (name, age, email).<br><strong>Example of an Array</strong>: A list of all the user's favorite book titles.</p>
<h3 id="heading-ifelse-statements-switch-statements">If/else Statements, Switch Statements</h3>
<p>These are like decision-making processes. <a target="_blank" href="https://www.freecodecamp.org/news/javascript-if-else-and-if-then-js-conditional-statements/">If/else statements</a> are like choosing what to wear based on the weather, and switch statements are like a more complex decision, like choosing what to cook based on multiple ingredients you have.  </p>
<p><strong>Example</strong>: If it's raining (if), take an umbrella (else), take sunglasses.</p>
<h3 id="heading-callbackspromisesasync-await">Callbacks/Promises/Async Await</h3>
<p>These are ways to handle tasks that take some time, like ordering food and waiting for it. <a target="_blank" href="https://www.freecodecamp.org/news/what-is-a-callback-function-in-javascript-js-callbacks-example-tutorial/">Callbacks</a> are like calling a friend to do something when they’re free. <a target="_blank" href="https://www.freecodecamp.org/news/javascript-promises-async-await-and-promise-methods/">Promises</a> are like your friend promising to do it. <a target="_blank" href="https://www.freecodecamp.org/news/javascript-async-await/">Async-await</a> is like making a plan to do tasks one after another in an organized way.  </p>
<p><strong>Example</strong>: Ordering a coffee (a task) and waiting to get it before leaving the cafe (ensuring order of actions).</p>
<h3 id="heading-ecmascript-template-strings-destructuring-assignment-spread-operator-default-parameters-and-so-on">ECMAScript (Template Strings, Destructuring Assignment, Spread Operator, Default Parameters, and so on)</h3>
<p>These are advanced tools and shortcuts in JavaScript to make coding easier and cleaner. It's like having a food processor in your kitchen that makes chopping and mixing faster and more efficient.  </p>
<p><strong>Example</strong>: Automatically creating a welcome message like "Hello, [Name]!" without manually joining words and variables.</p>
<h3 id="heading-typescript">TypeScript</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/typescript-tutorial-for-react-developers/">TypeScript</a> is like JavaScript but with more rules for organizing your code (like a more detailed recipe book). It helps in managing larger projects by adding types to your code, making sure you don’t mix incompatible ingredients. <a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-beginners-guide/">This guide</a> teaches you TypeScript basics.  </p>
<p><strong>Example</strong>: Specifying that a function should only take a number as an input, not text or anything else. </p>
<h2 id="heading-step-2-get-familiar-with-react">STEP 2: Get Familiar with React</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/communityIcon_4g1uo0kd87c61.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once you've got a feel for JavaScript, its time to venture into the wonderful world of frontend development. </p>
<p>React.js is a popular JavaScript library used for building user interfaces, particularly known for its efficiency in rendering dynamic, interactive web pages. It enables developers to create large web applications that can change data, without reloading the page, making for a smoother user experience.</p>
<p>Below is a list of common things you want to know when working with React.</p>
<h3 id="heading-components">Components</h3>
<p>Think of <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-react-components/">components</a> as individual LEGO blocks in a large LEGO model. Each block is a small, reusable piece that you can use to build different parts of your web application.  </p>
<p><strong>Example</strong>: A 'button' component in a website that can be used in many places, like for submitting a form or closing a pop-up.</p>
<h3 id="heading-jsx-javascript-xml">JSX (JavaScript XML)</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/jsx-in-react-introduction/">JSX</a> lets you write your website's design code (like HTML) inside your JavaScript code. It's like writing the recipe and the cooking instructions in one place for easier reference.  </p>
<p><strong>Example</strong>: Writing a piece of JSX code that includes both JavaScript and HTML-like tags to create a user login form.</p>
<h3 id="heading-props-properties">Props (Properties)</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/props-in-react/">Props are like instructions</a> or settings you pass to your LEGO blocks (components) to tell them what they should look like or do.  </p>
<p><strong>Example</strong>: Passing a 'color' prop to a 'button' component to make it red or blue depending on the situation.</p>
<h3 id="heading-state">State</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/usestate-vs-redux-state-management/">State</a> is like a personal notebook for each component, where it keeps track of its own information, like whether a button is clicked or not. Here's a course all about <a target="_blank" href="https://www.freecodecamp.org/news/how-to-manage-state-in-react/">state management in React</a>.</p>
<p><strong>Example</strong>: A 'like' button keeping track of whether it has been clicked (liked) or not.</p>
<h3 id="heading-hooks">Hooks</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/react-hooks-useeffect-usestate-and-usecontext/">Hooks are special tools in React</a> that let you add features like state to your components without needing to use complex code structures.</p>
<p><strong>Example</strong>: Using the useState hook to keep track of a counter in a component.</p>
<h3 id="heading-event-handling">Event Handling</h3>
<p>This is how you tell a component to do something when a user interacts with it, like clicking a button or entering text in a form.  </p>
<p><strong>Example</strong>: Setting up an event handler so that when a user clicks a 'submit' button, it sends their information to the server.</p>
<h3 id="heading-conditional-rendering">Conditional Rendering</h3>
<p>This is like having a magic painting that can change its picture based on certain conditions. In React, you can <a target="_blank" href="https://www.freecodecamp.org/news/react-conditional-rendering/">show different components based on different conditions</a>.</p>
<p><strong>Example</strong>: Showing a 'login' button if a user is not logged in, and a 'logout' button if they are.</p>
<h3 id="heading-lists-and-keys">Lists and Keys</h3>
<p>Keys are like name tags for items in a list. They help React keep track of which items are new, changed, or removed.  </p>
<p><strong>Example</strong>: Displaying a list of messages in a chat app, where each message has a unique key.</p>
<h3 id="heading-context-api">Context API</h3>
<p><a target="_blank" href="https://www.freecodecamp.org/news/context-api-in-react/">The Context API</a> a way to share information (like a theme setting or user data) across many components without passing the information through each level manually.</p>
<p><strong>Example</strong>: Using Context API to share the current logged-in user's information across different components in a web app.</p>
<h3 id="heading-fragment">Fragment</h3>
<p>Fragments let you group several components or elements together without adding extra layers to the website. It's like putting multiple LEGO pieces on a baseplate without the baseplate being part of the final model.</p>
<p><strong>Example</strong>: Grouping a list of items together in a menu without adding extra wrappers or divs around them.</p>
<h2 id="heading-step-3-understand-rest-apis-and-how-a-backend-server-works-using-expressnode">STEP 3: Understand REST API's and how a backend server works using Express/Node</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/express-and-node-opengraph-v1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Every UI needs a way to store and retrieve the data it needs to make the frontend work. This is where our backend comes in. </p>
<p>In the MERN stack, the backend is composed of 3 main bits: Express, a Node.js server, and a database. We'll cover the database shortly, for now we'll focus on the Express/Node pieces of the MERN stack, as they're closely related.  </p>
<p>Express.js is a lightweight, flexible framework for Node.js, designed to build web applications and <a target="_blank" href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/">REST APIs</a> with ease and efficiency. Node.js is a powerful JavaScript runtime that allows for the development of scalable server-side applications, making the duo a popular choice for backend development.</p>
<h3 id="heading-nodejs-foundation-for-building-web-applications">Node.js: Foundation for Building Web Applications</h3>
<p>Think of Node.js as the foundation for constructing a modern building. It's a platform that lets you build web applications, similar to how you would use a set of basic tools and materials to start building a house. You might hear this being to referred to as the "backend".  </p>
<p><strong>Example</strong>: Building a chat application where multiple users can send messages in real-time.</p>
<h3 id="heading-express-streamlining-rest-api-development">Express: Streamlining REST API Development</h3>
<p>Express is a helper tool for Node.js. It's like having a pre-built kit that makes building certain parts of your house easier and faster, providing templates and shortcuts so you don't have to start from scratch. </p>
<p><strong>Example</strong>: Using Express to quickly set up routes for a website, like a route to a contact page or a product catalog.</p>
<h3 id="heading-modules-and-packages-ready-made-components">Modules and Packages: Ready-Made Components</h3>
<p>In Node.js, modules are like pre-made components or sections of a house (like a bathroom unit or a kitchen set) that you can simply choose and add to your building project.</p>
<p><strong>Example</strong>: Adding a 'date-time' module to display current times and dates on your web application.</p>
<h3 id="heading-node-package-manager-npm-the-tool-and-material-warehouse">Node Package Manager (NPM): The Tool and Material Warehouse</h3>
<p>NPM acts like a vast warehouse where you can find all sorts of tools and materials (modules) you might need. It's a central place to get additional resources for building your web applications.</p>
<p><strong>Example</strong>: Installing 'body-parser' from npm to handle JSON data in your web application.</p>
<h3 id="heading-routing-directing-web-traffic">Routing: Directing Web Traffic</h3>
<p>Routing in Express is like setting up roads and paths in a housing complex. It's about directing the flow of traffic (data and user requests) to different parts of your web application.</p>
<p><strong>Example</strong>: Creating routes in an online store, like <code>/products</code> for the product list and <code>/products/:id</code> for individual product details.</p>
<h3 id="heading-middleware-additional-functional-layers">Middleware: Additional Functional Layers</h3>
<p>Middleware in Express can be seen as extra layers or services in your building, like security, plumbing, or electrical systems. They add specific functionalities to your web application.</p>
<p><strong>Example</strong>: Adding 'cookie-parser' middleware to handle cookies in your web application.</p>
<h3 id="heading-request-and-response-communication-channels">Request and Response: Communication Channels</h3>
<p>Requests and responses in Express are like sending and receiving mail or messages. They are the way your web application communicates with users, sending them data or receiving their inputs.</p>
<p><strong>Example</strong>: Your application receiving a user's login request (request) and then sending back a confirmation message (response).</p>
<h3 id="heading-environment-variables-secure-storage-spaces">Environment Variables: Secure Storage Spaces</h3>
<p>Think of environment variables as secure storage spaces or safes in your building. They're used to store sensitive information like passwords or personal settings, keeping them secure and separate from the main construction.</p>
<p><strong>Example</strong>: Storing the database connection string in an environment variable to keep it secure.</p>
<h3 id="heading-security-building-safeguards">Security: Building Safeguards</h3>
<p>In the context of web applications, security is about building safeguards into your project. It's like installing locks, security systems, and fire safety measures in a building to protect it from various threats.</p>
<p><strong>Example</strong>: Implementing HTTPS to secure data transmission and using JWT (JSON Web Tokens) for user authentication to protect user data.</p>
<h2 id="heading-step-4-storing-data-with-mongodb-and-mongoose">STEP 4: Storing data with MongoDB and Mongoose</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/MongoDB_Logo.svg.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>MongoDB is a NoSQL database that offers high flexibility and scalability for storing and managing data, making it ideal for handling large volumes and diverse types of data. </p>
<p>Mongoose is an Object Data Modeling (ODM) library for MongoDB, providing a straightforward schema-based solution to model application data, enhancing database interaction with useful features and validation.</p>
<h3 id="heading-mongodb-a-nosql-database">MongoDB: A NoSQL Database</h3>
<p>MongoDB is a type of database that stores data in a flexible, JSON-like format. This makes it different from traditional databases, which use tables and rows. It's great for handling large volumes of data and is very scalable.</p>
<p><strong>Example</strong>: Using MongoDB to store user profiles where each profile can have different fields.</p>
<h3 id="heading-collections-and-documents">Collections and Documents</h3>
<p>In MongoDB, data is stored in 'collections', which are similar to tables in a relational database. Inside these collections, data is stored in 'documents'. Think of a document as a single record in your collection, like an entry in a diary or a contact in an address book.</p>
<p><strong>Example</strong>: A 'users' collection with documents each representing a user with details like name and email.</p>
<h3 id="heading-mongoose-a-mongodb-object-modeling-tool">Mongoose: A MongoDB Object Modeling Tool</h3>
<p>Mongoose is a library for Node.js that makes it easier to interact with MongoDB. It provides a straightforward, schema-based solution to model your application data. It's like having a personal assistant to help manage the communication between your application and MongoDB.</p>
<p><strong>Example</strong>: Using Mongoose to easily add, retrieve, and manage user data in a MongoDB database.</p>
<h3 id="heading-schemas">Schemas</h3>
<p>In Mongoose, a schema is a structure that defines the format of the data to be stored in MongoDB (like defining fields and data types). Think of it as a blueprint for how your data should look.</p>
<p><strong>Example</strong>: Creating a Mongoose schema for a blog post with fields like title, author, and content.</p>
<h3 id="heading-models">Models</h3>
<p>A model in Mongoose acts as a constructor, compiled from the Schema definitions. It represents documents in a MongoDB database. Models are responsible for creating and reading documents from the underlying MongoDB database.</p>
<p><strong>Example</strong>: Defining a 'User' model based on a user schema to interact with the 'users' collection in the database.</p>
<h3 id="heading-crud-operations">CRUD Operations</h3>
<p>CRUD stands for Create, Read, Update, Delete. These are the basic operations you can perform on the database. Mongoose provides easy methods to execute these operations on your data.</p>
<p><strong>Example</strong>: Using Mongoose methods to add new users, find users by name, update user information, or delete users.</p>
<h3 id="heading-connecting-to-mongodb">Connecting to MongoDB</h3>
<p>You can use Mongoose to connect your Node.js application to a MongoDB database. This is like setting up a phone line between your application and the database so they can talk to each other.</p>
<p><strong>Example</strong>: Writing a Mongoose connect function to link your Node.js application to a MongoDB database hosted on Atlas.</p>
<h3 id="heading-querying-data">Querying Data</h3>
<p>Mongoose allows you to query your MongoDB database. This means you can search for specific data, filter your data based on certain criteria, and more.</p>
<p><strong>Example</strong>: Using a Mongoose query to find all blog posts written by a specific author.</p>
<h3 id="heading-data-validation">Data Validation</h3>
<p>Mongoose provides built-in validation. This is a way to make sure the data being saved to your database is in the right format, like checking if an email address looks like an email address.</p>
<p><strong>Example</strong>: Defining a schema in Mongoose where the email field must match the format of an email address.</p>
<h3 id="heading-middleware-pre-and-post-hooks">Middleware (Pre and Post Hooks)</h3>
<p>Mongoose middleware are functions which can be executed automatically before or after certain operations, like saving a document. They're useful for complex logic like hashing passwords before saving them to the database.</p>
<p><strong>Example</strong>: Using a pre-save middleware in Mongoose to hash user passwords before saving them to the database.</p>
<h3 id="heading-indexes">Indexes</h3>
<p>Indexes in MongoDB are used to improve the performance of searches. They are similar to indexes in a book, helping the database find data faster.</p>
<p><strong>Example</strong>: Creating an index on the 'email' field in a user collection to speed up the search for users by email.</p>
<h3 id="heading-aggregation">Aggregation</h3>
<p>Aggregation in MongoDB is a powerful way to process data and get computed results. It's like having a sophisticated calculator to perform complex operations on your data, such as summing up values or averaging them.</p>
<p><strong>Example</strong>: Using MongoDB's aggregation framework to calculate the average number of comments on blog posts.</p>
<h2 id="heading-step-5-writing-tests">STEP 5: Writing Tests</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/opengraph.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Testing in software development is like a safety check to ensure everything in your application works as expected. It's a crucial step in the development process where you look for bugs or issues before your users do. Think of it like proofreading an essay or checking a car before a road trip – it helps catch and fix problems early.</p>
<p>There are different types of testing, each serving a unique purpose:</p>
<h3 id="heading-unit-testing">Unit Testing</h3>
<p>This is the most basic form of testing. Here, you test individual parts of your code (like functions or components) in isolation. It's like checking each light bulb in a string of Christmas lights. </p>
<p>In the MERN stack, tools like Jest or Mocha are commonly used for this. They let you write small tests to check if a specific part of your application behaves as expected.</p>
<h3 id="heading-integration-testing">Integration Testing</h3>
<p>This type of testing checks how different parts of your application work together. It's like making sure all the light bulbs light up when connected and the string is plugged in. </p>
<p>For the MERN stack, you might still use Jest or Mocha, combined with other tools like Chai for assertions, to ensure that different components or services in your application interact correctly.</p>
<h3 id="heading-end-to-end-e2e-testing">End-to-End (E2E) Testing</h3>
<p>Here, you test your application's workflow from start to finish. It's like checking if the entire Christmas tree lights up and twinkles as expected. </p>
<p>For a MERN stack application, Cypress or Selenium are popular choices. They simulate real user scenarios, ensuring the entire application, from the front end in React to the back end with Express and Node.js, functions smoothly together.</p>
<h3 id="heading-performance-testing">Performance Testing</h3>
<p>This checks if your application can handle stress, like heavy traffic or data processing. It's akin to ensuring the Christmas tree lights don't blow a fuse when they're all on. Tools like Loader.io or Apache JMeter can be used here.</p>
<p>Each type of testing serves to ensure a different aspect of your application is working correctly, and together, they contribute to building a robust, reliable, and user-friendly application. </p>
<p>By employing these tests in the MERN stack, you not only catch bugs early but also maintain a high standard of quality for your application.</p>
<h2 id="heading-step-6-using-git">STEP 6: Using Git</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/629b7adc7c5cd817694c3231.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Git is a version control system, a tool that tracks changes in your code over time. Think of it like a detailed diary for your coding project. Every time you make changes to your code, Git keeps a record of what was changed, when, and by whom. This becomes incredibly useful when you’re working on complex projects, like those involving the MERN stack.</p>
<p>Why is Git so important when building with the MERN stack, or any software for that matter? </p>
<h3 id="heading-collaboration">Collaboration</h3>
<p>Git is like a team playbook. It allows multiple developers to work on the same project without stepping on each other's toes. </p>
<p>Everyone can work on different features or parts of the application simultaneously (like MongoDB database schemas, React components, or Express.js routes). Git helps manage these contributions, ensuring changes can be merged smoothly into the main project.</p>
<h3 id="heading-tracking-changes">Tracking Changes</h3>
<p>Imagine you've made changes to your React component, and suddenly things aren't working as they used to. Git allows you to go back in time and see what changes were made and by whom. </p>
<p>This historical data is invaluable for understanding how your project evolved and for fixing issues without having to start from scratch.</p>
<h3 id="heading-branching-and-merging">Branching and Merging</h3>
<p>Git’s branching feature lets you diverge from the main line of development and experiment with new features or ideas in a controlled way. </p>
<p>You can create a branch, make your changes, and then merge those changes back into the main project when they're ready. This ensures the main project (often referred to as the 'master' or 'main' branch) remains stable.</p>
<h3 id="heading-backup-and-restore">Backup and Restore</h3>
<p>With Git, your project's entire history is stored in the repository. If anything goes wrong, you can roll back to a previous state. It’s like having a fail-safe backup system.</p>
<h3 id="heading-documentation">Documentation</h3>
<p>Commit messages in Git provide a narrative for your project. They allow you to document what changes were made and why, which is extremely helpful for both your future self and other developers who might work on the project.</p>
<p>When building applications with the MERN stack, Git offers a safety net and a collaborative workspace. It keeps your project organized, tracks every change, and allows multiple developers to work together more efficiently. </p>
<p>Using Git is essential for managing complex development projects in today's software development world.</p>
<h2 id="heading-step-7-deployments">STEP 7: Deployments</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/img-blog-cico.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Code deployment is the process of taking code written by developers and making it operational on a live environment where users can interact with it. </p>
<p>In the context of the MERN stack, which involves technologies like MongoDB, Express.js, React, and Node.js, deployment is the final step in the journey of bringing a full-stack application to life.</p>
<p>Imagine you've built a house (your web application). Deployment is like moving it from the construction site (development environment) to its actual location where people can live in it (production environment). This process involves several key steps to ensure that everything works as expected when users access your app.</p>
<h3 id="heading-preparing-for-deployment">Preparing for Deployment</h3>
<p>Before deploying, you need to prepare your application. This involves ensuring your code is complete and tested, dependencies are properly managed, and your app is configured for the production environment. </p>
<p>For MERN stack applications, this might mean setting up environment variables, configuring your database (MongoDB) connection for production, and optimizing your React front-end for performance.</p>
<h3 id="heading-hosting-and-servers">Hosting and Servers</h3>
<p>Choosing where to host your application is crucial. For MERN stack apps, you can use cloud-based hosting services like AWS, Heroku, or DigitalOcean. These platforms offer services to host both your Node.js backend and MongoDB database, and they often provide additional features like scaling, monitoring, and security.</p>
<h3 id="heading-continuous-integrationcontinuous-deployment-cicd">Continuous Integration/Continuous Deployment (CI/CD)</h3>
<p>CI/CD is a methodology that automates the deployment process. Whenever you make changes to your codebase (like fixing a bug or adding a new feature), CI/CD tools automatically test your code and deploy it if the tests pass. This ensures that your application is always up-to-date with the latest changes. </p>
<p>Tools like Jenkins, Travis CI, or GitHub Actions are commonly used for this purpose.</p>
<h3 id="heading-monitoring-and-maintenance">Monitoring and Maintenance</h3>
<p>After deployment, it’s important to monitor your application for any issues and perform regular maintenance. This could involve checking server logs, updating dependencies, or rolling out fixes for any bugs that might arise.</p>
<h3 id="heading-rollbacks">Rollbacks</h3>
<p>A good deployment strategy also includes plans for rollbacks. If something goes wrong after deployment, you need to be able to revert to the previous version quickly to minimize downtime.</p>
<p>In the MERN stack, each component (MongoDB, Express.js, React, and Node.js) might require specific considerations for deployment. For instance, you might use Docker containers to package your Node.js and Express.js backend, ensuring it runs consistently across different environments. React apps might be minified and bundled for optimal performance.</p>
<p>In essence, deployment in the MERN stack is about getting your application from your local machine to a server where it can serve users reliably and efficiently. It involves careful planning, choosing the right hosting solutions, automating the process as much as possible, and being prepared to address issues post-deployment.</p>
<h2 id="heading-top-resources-to-learn-the-mern-stack">Top Resources to Learn the MERN Stack</h2>
<p>Now that you have a pretty good idea of what you need to learn to master the MERN stack, lets look at a list of free resources you can start using today to begin your journey!</p>
<ul>
<li>The <a target="_blank" href="https://www.freecodecamp.org/learn/">freeCodeCamp curriculum</a> is one of the best places to learn how to code for free. The curriculum is super in depth and covers alot of the topics mentioned in this post.</li>
<li>The freeCodeCamp YouTube channel has a ton of free courses you can try as well. <a target="_blank" href="https://www.youtube.com/watch?v=-42K44A1oMA&amp;t=2950s">This MERN stack book project is an excellent one for beginners</a>.</li>
<li><a target="_blank" href="https://fullstackopen.com/">Full Stack open</a> is another good resource. It doesn't teach MongoDB but you learn about SQL instead which is equally as useful.</li>
<li>My <a target="_blank" href="https://www.youtube.com/watch?v=YdBy9-0pER4">MERN stack hotel booking app project on YouTube is a free 15 hour course</a> where you will learn everything talked about in this post.</li>
</ul>
<h2 id="heading-10-project-ideas-you-can-try-today">10 Project Ideas You Can Try Today</h2>
<p>One of my favourite ways to learn new technologies is to build projects. If you're struggling with coming up with ideas, here's 10 projects you can start building today. I'll be building some of these on my <a target="_blank" href="https://www.youtube.com/@ChrisBlakely">YouTube channel</a> so feel free to subscribe to stay up to date!</p>
<h3 id="heading-personal-blog-website">Personal Blog Website</h3>
<ul>
<li><strong>Functionality</strong>: Users can read posts, and the admin can create, edit, or delete posts.</li>
<li><strong>Learning Focus</strong>: Basic CRUD operations, user authentication, integrating React with Express API, and using MongoDB for data storage.</li>
</ul>
<h3 id="heading-task-manager-to-do-list">Task Manager (To-Do List)</h3>
<ul>
<li><strong>Functionality</strong>: Users can add, view, edit, and delete tasks. Tasks can have deadlines and priority levels.</li>
<li><strong>Learning Focus</strong>: React state management, Express route handling, MongoDB operations, and basic UI development.</li>
</ul>
<h3 id="heading-simple-e-commerce-site">Simple E-commerce Site</h3>
<ul>
<li><strong>Functionality</strong>: Display products, add to cart, and checkout functionality. Admin features for adding or removing products.</li>
<li><strong>Learning Focus</strong>: React components for product listing, cart management, Express.js for product APIs, MongoDB for product data, and handling user inputs.</li>
</ul>
<h3 id="heading-recipe-sharing-application">Recipe Sharing Application</h3>
<ul>
<li><strong>Functionality</strong>: Users can post, view, edit, and delete recipes. Implement a rating or comment system for interaction.</li>
<li><strong>Learning Focus</strong>: File upload for images, user-generated content management, and MongoDB schema design.</li>
</ul>
<h3 id="heading-budget-tracker">Budget Tracker</h3>
<ul>
<li><strong>Functionality</strong>: Users can input their expenses and income, categorize them, and view a summary of their finances.</li>
<li><strong>Learning Focus</strong>: Handling forms in React, creating RESTful services with Express, and effective data structuring in MongoDB.</li>
</ul>
<h3 id="heading-event-planning-application">Event Planning Application:</h3>
<ul>
<li><strong>Functionality</strong>: Users can create and manage events, send invitations, and track RSVPs.</li>
<li><strong>Learning Focus</strong>: Date handling in JavaScript, complex MongoDB documents, and Express middleware for authentication.</li>
</ul>
<h3 id="heading-fitness-tracker">Fitness Tracker:</h3>
<ul>
<li><strong>Functionality</strong>: Log workouts, track progress over time, set fitness goals.</li>
<li><strong>Learning Focus</strong>: Data visualization with React, creating API endpoints for varied data types, and MongoDB for storing time-series data.</li>
</ul>
<h3 id="heading-chat-application">Chat Application:</h3>
<ul>
<li><strong>Functionality</strong>: Real-time chat rooms, private messaging, and user profiles.</li>
<li><strong>Learning Focus</strong>: WebSockets with Node.js for real-time communication, MongoDB for message storage, and React for dynamic UI updates.</li>
</ul>
<h3 id="heading-book-review-platform">Book Review Platform:</h3>
<ul>
<li><strong>Functionality</strong>: Users can post book reviews, rate books, and browse reviews by other users.</li>
<li><strong>Learning Focus</strong>: Integrating external APIs for book data, user-generated content moderation, and complex querying in MongoDB.</li>
</ul>
<h3 id="heading-local-business-directory">Local Business Directory:</h3>
<ul>
<li><strong>Functionality</strong>: Listing of local businesses with categories, user reviews, and contact information.</li>
<li><strong>Learning Focus</strong>: Geolocation, advanced querying and indexing in MongoDB, and creating a responsive layout with React.</li>
</ul>
<h2 id="heading-wrapping-up-the-mern-stack-journey">Wrapping Up the MERN Stack Journey</h2>
<p>As we reach the end of our exploration of the MERN stack, I hope this guide has illuminated the path for your journey into the world of full-stack development. </p>
<p>We've covered the fundamental components – MongoDB, Express.js, React, and Node.js – and delved into the practical aspects of building, testing, and deploying applications using this versatile stack.</p>
<p>Remember, the road to mastering the MERN stack is both challenging and rewarding. Each project you undertake will add to your skills and confidence. Use the resources and project ideas provided as stepping stones to build your portfolio and deepen your understanding. </p>
<p>The beauty of the MERN stack lies in its community-driven nature, so don't hesitate to seek help, collaborate, and share your experiences.  </p>
<p>If you want to get in touch, you can reach me over at <a target="_blank" href="https://www.linkedin.com/in/chrisblakely01/">LinkedIn</a>, or drop a comment on my <a target="_blank" href="https://www.youtube.com/@ChrisBlakely">YouTube channel</a>. Good luck and happy coding! </p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/undefined" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Full Stack Project Tutorial – Create a Recipe App Using React, Node.js and PostgreSQL ]]>
                </title>
                <description>
                    <![CDATA[ In this in-depth tutorial, we'll build a full stack recipe app from scratch, using React, Node.js, Postgres and the Spoonacular API. We'll cover features such as: Building an API server in Node Integrating securely with a 3rd party API Interacting w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/full-stack-project-create-a-recipe-app-using-react-node-js/</link>
                <guid isPermaLink="false">66c8c8d4c4cede4e0083f737</guid>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ postgres ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Thu, 19 Oct 2023 20:31:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/react-note-photo-gallery-app--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this in-depth tutorial, we'll build a full stack recipe app from scratch, using React, Node.js, Postgres and the Spoonacular API. We'll cover features such as:</p>
<ul>
<li>Building an API server in Node</li>
<li>Integrating securely with a 3rd party API</li>
<li>Interacting with a Postgres database using Prisma</li>
<li>Making API requests from React</li>
<li>Creating reusable components</li>
<li>Working with pagination</li>
<li>Working with UI elements such as tabs, image grids, modals and styling</li>
</ul>
<p>Let's dive in.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#try-it-yourself-first">GitHub Repositor</a>ies</li>
<li><a class="post-section-overview" href="#heading-video-tutorial">Video Tutorial</a></li>
<li><a class="post-section-overview" href="#heading-project-architecture">Project Architecture</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-the-backend">How to Setup the Backend</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-the-database-and-prisma">How to Setup the Database and Prisma</a></li>
<li><a class="post-section-overview" href="#heading-how-to-get-and-secure-a-spoonacular-api-key">How to Get and Secure a Spoonacular API Key</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-search-endpoint">How to Create the Search Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-the-frontend">How to Setup the Frontend</a></li>
<li><a class="post-section-overview" href="#heading-how-to-call-the-search-api-and-display-results-on-the-frontend">How to Call the Search API and Display Results on the Frontend</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-search-input-and-recipe-card-component">How to Create the Search Input and Recipe Card Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-pagination-and-view-more-functionality">How to Build the Pagination and View More Functionality</a></li>
<li><a class="post-section-overview" href="#how-to-build-the-recipe-summary-and-build-more-component">How to Build the Recipe Summary Modal Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-endpoints-to-getcreatedelete-favorite-recipes">How to Create Endpoints to Get/Create/Delete Favorite Recipes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-favorites-functionality-to-the-frontend">How to Add Favorites Functionality to the Frontend</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-cssstyling">How to Adding CSS/Styling</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Since we will be focusing on how to build a project, there are a few prerequisites that will be needed to get the most out of this tutorial:</p>
<ul>
<li>Some knowledge about web development concepts (frontend, backend, databases, API's, REST).</li>
<li>Some knowledge of JavaScript (variables, functions, objects, arrays, and so on).</li>
<li>Basic understanding on React (how to create components, add styles, work with state).</li>
<li>Basic understanding on Node.js/Express (working with APIs).</li>
</ul>
<h2 id="heading-github-repositories">GitHub Repositories</h2>
<h3 id="heading-completed-code">Completed Code</h3>
<p><a target="_blank" href="https://github.com/chrisblakely01/react-node-recipe-app">You can find the completed code on GitHub by clicking here,</a> or clone the repo:</p>
<pre><code>git clone git@github.com:chrisblakely01/react-node-recipe-app.git
</code></pre><h3 id="heading-starter-code">Starter Code</h3>
<p>If you want to save some time and skip the initial setup, <a target="_blank" href="https://github.com/chrisblakely01/react-node-recipe-app-starter">you can find the starter code here.</a> This has a skeleton frontend/backend project already setup, as well as the basic layout and CSS. Or clone the repo:</p>
<pre><code>git clone git@github.com:chrisblakely01/react-node-recipe-app-starter.git
</code></pre><h2 id="heading-video-tutorial">Video Tutorial</h2>
<p>If you'd like to learn from the video version as well, here it is:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5wwaQ4GiSNU" 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>
<h2 id="heading-project-architecture">Project Architecture</h2>
<p>Here's a diagram that illustrates how the various components of our app will interact with each other:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/recipe-app-architecture.png" alt="recipe-app-architecture" width="600" height="400" loading="lazy">
<em>Diagram illustrating the various components of the app</em></p>
<p>We will have a React front end and a Node backend. These two will communicate through specific endpoints. We will establish five endpoints, all housed within our backend.</p>
<p>We can categorize these endpoints into two distinct groups. The first group will cater to recipe searches. It will invoke the recipe API and return the results based on a given search query. Our front end will initiate a call to our backend, which will then relay the search request to the recipe API. </p>
<p>We choose not to call the recipe API directly from our front end because it requires an API key—a form of authentication similar to a password. Exposing this key in our front end code could lead to unauthorized access if someone delves into the code through their browser to retrieve the API key.</p>
<p>It's a more secure practice to house the API key on our backend within environment variables. From there, we can call the recipe API and then transmit the response back to our front end. </p>
<p>This approach aligns with common practices in production environments. It also offers the flexibility to modify the data on the backend, if necessary, before sending it back to the front end. And it enhances performance, as the UI will not have to manage multiple API requests to and from the recipe API.</p>
<p>That's the essence of how our search functionality will operate. We'll also have several endpoints to add, create, and delete favorites. These favorites will be stored in our own database, providing a clear picture of what we aim to build.</p>
<h2 id="heading-how-to-setup-the-backend">How to Setup the Backend</h2>
<p>In this tutorial, we will walk through the process of building a full-stack recipe application. We'll set up the backend, create the frontend, and link it to a database. We will also connect to a recipe API using an API key. </p>
<p>If you prefer to skip the setup, a starter code is available on CodeCoyotes, which includes some basic setup and CSS. But you'll still need to create a database and obtain an API key.</p>
<p>Let’s start by setting up our workspace:</p>
<h3 id="heading-step-1-setup-your-workspace">Step 1: Setup Your Workspace</h3>
<p>Start by opening Visual Studio Code (or your preferred code editor). Create a new folder named <code>recipe-app</code> on your desktop or another location. Then drag this folder into the Visual Studio Code window to open it.</p>
<p>Your folder structure should now look like this:</p>
<pre><code class="lang-plaintext">recipe-app
</code></pre>
<h3 id="heading-step-2-setup-the-backend">Step 2: Setup the Backend</h3>
<p>In the <code>recipe-app</code> folder, create another folder named <code>backend</code>.</p>
<p>Navigate to <code>View -&gt; Terminal</code> in Visual Studio Code to open a terminal. Change your directory to the <code>backend</code> folder using the command <code>cd backend</code>.</p>
<p>Type <code>npm init</code> to initialize a new npm package, then hit Enter to move through the prompts. For the entry point, type <code>./src/index.ts</code> and hit Enter.</p>
<p>Your folder structure should now look like this:</p>
<pre><code class="lang-plaintext">recipe-app
|-- backend
    |-- package.json
</code></pre>
<h3 id="heading-step-3-install-the-dependencies">Step 3: Install the Dependencies</h3>
<p>First, install the necessary dependencies using the following command:</p>
<pre><code class="lang-bash">npm install express prisma @prisma/client cors
</code></pre>
<p>Now, install the development dependencies:</p>
<pre><code class="lang-bash">npm install --save-dev ts-node typescript nodemon @types/cors @types/express @types/node
</code></pre>
<p>Your folder structure should now look like this:</p>
<pre><code class="lang-plaintext">recipe-app
|-- backend
    |-- node_modules
    |-- package.json
    |-- package-lock.json
</code></pre>
<h3 id="heading-step-4-setup-your-backend-code">Step 4: Setup Your Backend Code</h3>
<p>In the <code>backend</code> folder, create a new folder named <code>src</code>. Inside <code>src</code>, create a file named <code>index.ts</code>.</p>
<p>Add the following code to <code>index.ts</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> cors <span class="hljs-keyword">from</span> <span class="hljs-string">"cors"</span>;

<span class="hljs-keyword">const</span> app = express();

app.use(express.json());
app.use(cors());

app.get(<span class="hljs-string">"/api/recipe/search"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"success"</span> });
});

app.listen(<span class="hljs-number">5000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server running on localhost:5000"</span>);
});
</code></pre>
<h3 id="heading-step-5-add-the-start-script">Step 5: Add the Start Script</h3>
<p>First, open <code>package.json</code> in the <code>backend</code> folder. In the <code>scripts</code> section, replace the <code>test</code> script with a <code>start</code> script as follows:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"npx nodemon ./src/index.ts"</span>
}
</code></pre>
<h3 id="heading-step-6-run-your-backend">Step 6: Run Your Backend</h3>
<p>In the terminal, ensure you are in the <code>backend</code> folder, then type <code>npm start</code> to run your backend server.</p>
<p>Then open a browser and go to <code>http://localhost:5000/api/recipe/search</code>. You should see a response with the message <code>success</code>.</p>
<p>Congratulations! You have successfully set up and run your backend server. In the next part of this tutorial, we will focus on setting up the frontend and connecting to a database.</p>
<h2 id="heading-how-to-setup-the-database-and-prisma">How to Setup the Database and Prisma</h2>
<p>In this section, we'll focus on setting up a Postgres database using ElephantSQL and integrating Prisma to interact with our database effortlessly. Let's jump right in!</p>
<h3 id="heading-step-1-set-up-the-elephantsql-database">Step 1: Set Up the ElephantSQL Database</h3>
<p>Start by navigating to <a target="_blank" href="https://www.elephantsql.com/">ElephantSQL</a>. Click on "Get a managed database today," followed by selecting the "Tiny Turtle" plan for a free instance.</p>
<p>Sign in or create an account to proceed to the "Create new instance" page.</p>
<p>Then enter a name for your database (for example, <code>recipe-app-db</code>), keep the plan on the free tier, and choose a region closest to you.</p>
<p>Click on "Review," verify the details, and then click on "Create instance."</p>
<h3 id="heading-step-2-retrieve-the-database-credentials">Step 2: Retrieve the Database Credentials</h3>
<p>Once your instance is created, click on it to view the details.</p>
<p>Locate and copy the URL under the "Details" section. This URL contains the credentials needed to connect to your database.</p>
<h3 id="heading-step-3-create-an-environment-file">Step 3: Create an Environment File</h3>
<p>Now, return to your code editor and open the <code>backend</code> folder.</p>
<p>Create a new file named <code>.env</code>. Inside the <code>.env</code> file, add the following line:</p>
<pre><code class="lang-plaintext">DATABASE_URL=&lt;Your-Copied-Database-URL&gt;
</code></pre>
<p>Replace <code>&lt;Your-Copied-Database-URL&gt;</code> with the URL you copied from ElephantSQL.</p>
<h3 id="heading-step-4-integrate-prisma">Step 4: Integrate Prisma</h3>
<p>Stop your server if it's running by pressing <code>Ctrl + C</code> (or <code>Cmd + C</code> on Mac) in the terminal.</p>
<p>In the terminal, ensure you are in the <code>backend</code> directory, and type the following command to initialize Prisma:</p>
<pre><code class="lang-bash">npx prisma init
</code></pre>
<p>This command will create a new folder named <code>prisma</code> with a file named <code>schema.prisma</code>.</p>
<h3 id="heading-step-5-verify-prisma-integration">Step 5: Verify Prisma Integration</h3>
<p>Now, open <code>prisma/schema.prisma</code> to ensure your <code>DATABASE_URL</code> has been detected correctly.</p>
<p>Start your server again with the command <code>npm start</code>. Then navigate to <code>http://localhost:5000/api/recipe/search</code> in your browser to ensure your API still works and returns the success message.</p>
<p>Your folder structure should now include the Prisma folder and look like this:</p>
<pre><code class="lang-plaintext">recipe-app
|-- backend
    |-- prisma
        |-- schema.prisma
    |-- .env
    |-- ...
</code></pre>
<h2 id="heading-how-to-get-and-secure-a-spoonacular-api-key">How to Get and Secure a Spoonacular API Key</h2>
<h3 id="heading-step-1-obtain-an-api-key-from-spoonacular">Step 1: Obtain an API Key from Spoonacular</h3>
<p>To do this, navigate to <a target="_blank" href="https://spoonacular.com/">Spoonacular</a> and click on "Start Now." Sign up for an account and proceed to the dashboard.</p>
<p>Within the dashboard, click on “Profile” on the left-hand side, and find the section related to API keys. Generate a new API key, and copy it to your clipboard.</p>
<h3 id="heading-step-2-store-the-api-key-securely">Step 2: Store the API Key Securely</h3>
<p>Now, return to your code editor and open the <code>.env</code> file in the <code>backend</code> folder.</p>
<p>Add a new environment variable to store your API key as follows:</p>
<pre><code class="lang-plaintext">API_KEY=&lt;Your-Copied-API-Key&gt;
</code></pre>
<p>Replace <code>&lt;Your-Copied-API-Key&gt;</code> with the API key you copied from Spoonacular.</p>
<h3 id="heading-step-3-install-and-setup-thunder-client">Step 3: Install and Setup Thunder Client</h3>
<p>In Visual Studio Code, navigate to the extensions tab (square icon on the sidebar), and search for Thunder Client.</p>
<p>Install Thunder Client by clicking on the Install button. Once installed, you will see a new icon (a purple thunderbolt) on the sidebar.</p>
<h3 id="heading-step-4-test-the-api-key-with-thunder-client">Step 4: Test the API Key with Thunder Client</h3>
<p>Now click on the Thunder Client icon, then click on “New Request.”</p>
<p>Copy the endpoint URL for searching recipes from Spoonacular's documentation. It should look something like this: <code>https://api.spoonacular.com/recipes/complexSearch</code>.</p>
<p>Paste this URL into the URL bar in Thunder Client.</p>
<p>Under the query tab, add two new parameters:</p>
<ul>
<li><code>apiKey</code> with the value of your API key.</li>
<li><code>query</code> with a value of <code>burgers</code> or any other term you wish to search for.</li>
</ul>
<p>Then hit "Send" to issue the request and observe the response. You should see a list of recipes related to the term you searched for, indicating that your API key and endpoint are working correctly.</p>
<h2 id="heading-how-to-create-the-search-endpoint">How to Create the Search Endpoint</h2>
<h3 id="heading-step-1-setup-a-new-file-for-recipe-api-logic">Step 1: Setup a New File for Recipe API Logic</h3>
<p>First, navigate to your <code>backend/src</code> folder and create a new file named <code>recipe-api.ts</code>.</p>
<p>In <code>recipe-api.ts</code>, initiate a constant to store your API key from the environment variables:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> API_KEY = process.env.API_KEY;
</code></pre>
<h3 id="heading-step-2-create-the-searchrecipes-function">Step 2: Create the searchRecipes Function</h3>
<p>In <code>recipe-api.ts</code>, define a new asynchronous function <code>searchRecipes</code> that takes in a <code>searchTerm</code> and a <code>page</code> as parameters:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> searchRecipes = <span class="hljs-keyword">async</span> (searchTerm: <span class="hljs-built_in">string</span>, page: <span class="hljs-built_in">number</span>) =&gt; {
  <span class="hljs-keyword">if</span> (!API_KEY) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"API key not found"</span>);
  }

  <span class="hljs-keyword">const</span> baseURL = <span class="hljs-string">"https://api.spoonacular.com/recipes/complexSearch"</span>;
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(baseURL);

  <span class="hljs-keyword">const</span> queryParams = {
    apiKey: API_KEY,
    query: searchTerm,
    <span class="hljs-built_in">number</span>: <span class="hljs-number">10</span>,
    offset: (page - <span class="hljs-number">1</span>) * <span class="hljs-number">10</span>,
  };

  url.search = <span class="hljs-keyword">new</span> URLSearchParams(queryParams).toString();

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> searchResponse = <span class="hljs-keyword">await</span> fetch(url.toString());
    <span class="hljs-keyword">const</span> resultsJson = <span class="hljs-keyword">await</span> searchResponse.json();
    <span class="hljs-keyword">return</span> resultsJson;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
  }
};
</code></pre>
<h3 id="heading-step-3-import-and-use-searchrecipes-in-indexts">Step 3: Import and Use <code>searchRecipes</code> in index.ts</h3>
<p>Now, navigate back to <code>index.ts</code> in the <code>backend/src</code> folder.</p>
<p>Import the <code>searchRecipes</code> function from <code>recipe-api.ts</code> at the top of your file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> RecipeAPI <span class="hljs-keyword">from</span> <span class="hljs-string">"./recipe-api"</span>;
</code></pre>
<p>Locate the endpoint where you wish to utilize the <code>searchRecipes</code> function, and modify it to call <code>searchRecipes</code> with the appropriate arguments, then return the results:</p>
<pre><code class="lang-typescript">app.get(<span class="hljs-string">"/api/recipe/search"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> searchTerm = req.query.searchTerm <span class="hljs-keyword">as</span> <span class="hljs-built_in">string</span>;
  <span class="hljs-keyword">const</span> page = <span class="hljs-built_in">parseInt</span>(req.query.page <span class="hljs-keyword">as</span> <span class="hljs-built_in">string</span>);

  <span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> recipeAPI.searchRecipes(searchTerm, page);
  <span class="hljs-keyword">return</span> res.json(results);
});
</code></pre>
<h3 id="heading-step-4-test-your-endpoint">Step 4: Test Your Endpoint</h3>
<p>Now you can restart your server by stopping it (<code>Ctrl + C</code> or <code>Cmd + C</code> on Mac) and then running <code>npm start</code>.</p>
<p>Test your endpoint by sending a GET request with the appropriate query parameters. For example, navigate to <code>http://localhost:5000/api/recipe/search?searchTerm=burgers&amp;page=1</code> in your browser or use a REST client like Postman or Thunder Client.</p>
<p>You should now see a list of recipes returned in response to your request, indicating that your backend logic for calling the Recipe API and returning the results is functioning as expected.</p>
<h2 id="heading-how-to-setup-the-frontend">How to Setup the Frontend</h2>
<p>Before you get started on this section, make sure you're in the top-level directory of your project, which in this case is named <code>recipe-app</code>.</p>
<h3 id="heading-step-1-create-a-react-app-with-vite">Step 1: Create a React App with Vite</h3>
<p>Start by opening a terminal and ensuring you're in the top-level folder (<code>recipe-app</code>).</p>
<p>Then run the following command to install the latest version of Vite:</p>
<pre><code class="lang-bash">npm install vite@latest --save-dev
</code></pre>
<p>Now, initiate a new React project with Vite by running:</p>
<pre><code class="lang-bash">npx create-vite frontend --template react-ts
</code></pre>
<p>This command creates a new folder named <code>frontend</code>, sets it up as a React project, and specifies TypeScript as the language.</p>
<h3 id="heading-step-2-navigate-to-your-new-react-app">Step 2: Navigate to Your New React App</h3>
<p>Change your directory to the <code>frontend</code> folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> frontend
</code></pre>
<p>Then install any necessary dependencies:</p>
<pre><code class="lang-bash">npm install
</code></pre>
<h3 id="heading-step-3-start-the-development-server">Step 3: Start the Development Server</h3>
<p>You can start the development server with the following command:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Your default web browser should now open displaying the initial setup of your React app, which includes a counter example.</p>
<h3 id="heading-step-4-clean-up-and-personalize-your-react-app">Step 4: Clean Up and Personalize Your React App</h3>
<p>Now you can head back to your code editor and navigate to <code>frontend/src</code>. Delete the <code>index.css</code> file as it won't be needed.</p>
<p>In <code>main.tsx</code>, remove the import statement for <code>index.css</code>.</p>
<p>Now, open <code>App.tsx</code>. Here, you'll see code for a counter. Delete all the content inside <code>App.tsx</code>.</p>
<p>Let’s start fresh by adding the following code to <code>App.tsx</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// src/App.tsx</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Hello from Recipe App<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>Save <code>App.tsx</code> and check your browser to see the updated text: "Hello from Recipe App".</p>
<h3 id="heading-step-5-setup-your-stylesheet">Step 5: Setup Your Stylesheet</h3>
<p>Go to <code>src</code> and open <code>App.css</code>. Delete all the pre-filled styles but keep the <code>.root</code> class definition empty for now.</p>
<p>Add a <code>font-family</code> property to the <code>.root</code> class:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* src/App.css */</span>
<span class="hljs-selector-class">.root</span> {
  <span class="hljs-attribute">font-family</span>: Helvetica, Arial, sans-serif;
}
</code></pre>
<p>Then head back to <code>App.tsx</code> and import your stylesheet:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// src/App.tsx</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>Then save <code>App.tsx</code> and check your browser to see the updated font.</p>
<p>Now you have a clean slate to start building out the frontend of your recipe app with React and TypeScript, using Vite as your build tool. As you progress, you can now start adding components, routing, and state management to build out your application's UI and functionality.</p>
<h2 id="heading-how-to-call-the-search-api-and-display-results-on-the-frontend">How to Call the Search API and Display Results on the Frontend</h2>
<p>Now we are going to fetch data from an API and display the results on the UI. The API response is structured as follows:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"results"</span>: [
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">650235</span>,
      <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Loaded Turkey Burgers"</span>,
      <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://spoonacular.com/recipeImages/650235-312x231.jpg"</span>,
      <span class="hljs-attr">"imageType"</span>: <span class="hljs-string">"jpg"</span>
    }
    <span class="hljs-comment">// ... other recipes</span>
  ],
  <span class="hljs-attr">"offset"</span>: <span class="hljs-number">10</span>,
  <span class="hljs-attr">"number"</span>: <span class="hljs-number">10</span>,
  <span class="hljs-attr">"totalResults"</span>: <span class="hljs-number">50</span>
}
</code></pre>
<p>Each recipe object contains an <code>id</code>, <code>title</code>, <code>image</code>, and <code>imageType</code>. We will map through the <code>results</code> array and display each recipe on our UI.</p>
<h3 id="heading-step-1-setup-state">Step 1: Setup State</h3>
<p>In your <code>App.tsx</code>, setup state to store the <code>searchTerm</code> and <code>recipes</code>.</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [searchTerm, setSearchTerm] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [recipes, setRecipes] = useState([]);

  <span class="hljs-comment">// ... rest of your component</span>
};
</code></pre>
<h3 id="heading-step-2-fetch-data-from-the-api">Step 2: Fetch Data from the API</h3>
<p>Create a new file <code>API.ts</code> and set up a function to make the API call.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// src/API.ts</span>
<span class="hljs-keyword">const</span> searchRecipes = <span class="hljs-keyword">async</span> (searchTerm: <span class="hljs-built_in">string</span>, page: <span class="hljs-built_in">number</span>) =&gt; {
  <span class="hljs-keyword">const</span> baseURL = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"http://localhost:5000/api/recipes/search"</span>);
  baseURL.searchParams.append(<span class="hljs-string">"searchTerm"</span>, searchTerm);
  baseURL.searchParams.append(<span class="hljs-string">"page"</span>, page.toString());

  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(baseURL.toString());

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

  <span class="hljs-keyword">return</span> response.json();
};

<span class="hljs-keyword">export</span> { searchRecipes };
</code></pre>
<h3 id="heading-step-3-create-a-handler-function">Step 3: Create a Handler Function</h3>
<p>Back in <code>App.tsx</code>, import the <code>searchRecipes</code> function and create a handler function to be called when the form is submitted.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, FormEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { searchRecipes } <span class="hljs-keyword">from</span> <span class="hljs-string">"./API"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// ... previous state setup</span>

  <span class="hljs-keyword">const</span> handleSearchSubmit = <span class="hljs-keyword">async</span> (event: FormEvent) =&gt; {
    event.preventDefault();

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { results } = <span class="hljs-keyword">await</span> searchRecipes(searchTerm, <span class="hljs-number">1</span>);
      setRecipes(results);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(error);
    }
  };

  <span class="hljs-comment">// ... rest of your component</span>
};
</code></pre>
<h3 id="heading-step-4-display-the-data">Step 4: Display the Data</h3>
<p>Display the recipes data in your component's return statement.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// ... previous code</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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearchSubmit}</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>
      {recipes.map((recipe) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{recipe.id}</span>&gt;</span>
          Recipe Image Location: {recipe.image}
          <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
          Recipe Title: {recipe.title}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-step-5-define-the-recipe-type">Step 5: Define the Recipe Type</h3>
<p>Define a <code>Recipe</code> interface in a new file named <code>types.ts</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// src/types.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Recipe {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  image: <span class="hljs-built_in">string</span>;
  imageType: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>Back in <code>App.tsx</code>, import the <code>Recipe</code> interface and use it to type your state and map function.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, FormEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { searchRecipes } <span class="hljs-keyword">from</span> <span class="hljs-string">'./API'</span>;
<span class="hljs-keyword">import</span> { Recipe } <span class="hljs-keyword">from</span> <span class="hljs-string">'./types'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [searchTerm, setSearchTerm] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [recipes, setRecipes] = useState&lt;Recipe[]&gt;([]);

  <span class="hljs-comment">// ... rest of your code</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* ... rest of your return statement */}
      {recipes.map((recipe: Recipe) =&gt; (
        {/* ... rest of your map function */}
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-step-6-test-your-setup">Step 6: Test Your Setup</h3>
<p>Now, start both your frontend and backend servers. Open your browser, navigate to your app, and try submitting a search. You should see the recipes data displayed on the screen.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># In one terminal</span>
<span class="hljs-built_in">cd</span> frontend
npm run dev

<span class="hljs-comment"># In another terminal</span>
<span class="hljs-built_in">cd</span> backend
npm start
</code></pre>
<p>This setup should now fetch and display recipe data based on the hardcoded <code>searchTerm</code> of "burgers". In a real-world scenario, you'd replace the hardcoded <code>searchTerm</code> with a dynamic value from a user input field.</p>
<h2 id="heading-how-to-create-the-search-input-and-recipe-card-component">How to Create the Search Input and Recipe Card Component</h2>
<h3 id="heading-step-1-setup-your-project">Step 1: Setup Your Project</h3>
<p>Start by setting up a new React project or navigate to your existing project directory.</p>
<pre><code class="lang-bash">npx create-react-app recipe-search-ui
<span class="hljs-built_in">cd</span> recipe-search-ui
</code></pre>
<h3 id="heading-step-2-create-state-hooks-for-user-input-and-data">Step 2: Create State Hooks for User Input and Data</h3>
<p>In your <code>src</code> folder, create a new file named <code>App.tsx</code> and import the necessary dependencies:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, FormEvent } <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> [searchTerm, setSearchTerm] = useState &lt; string &gt; <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> [recipes, setRecipes] = useState &lt; <span class="hljs-built_in">Array</span> &lt; any &gt;&gt; [];

  <span class="hljs-comment">// ... rest of the code</span>
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here, we have set up two state hooks: one for capturing the user's search term and another for holding the recipe data returned from the backend.</p>
<h3 id="heading-step-3-build-a-form-to-capture-user-input">Step 3: Build a Form to Capture User Input</h3>
<p>Within the <code>App</code> component, build a form with an input field and a submit button. We'll also create a function to handle the form submission, which will trigger the API call.</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// ... rest of the code</span>

  <span class="hljs-keyword">const</span> handleSearchSubmit = <span class="hljs-keyword">async</span> (event: FormEvent) =&gt; {
    event.preventDefault();
    <span class="hljs-comment">// ... API call logic</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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearchSubmit}</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">required</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter a search term"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{searchTerm}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setSearchTerm(event.target.value)}
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>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>
      {/* ... rest of the code */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now, users can enter their search term, and upon form submission, <code>handleSearchSubmit</code> will be triggered.</p>
<h3 id="heading-step-4-fetch-recipe-data-from-the-backend">Step 4: Fetch Recipe Data from the Backend</h3>
<p>In the <code>handleSearchSubmit</code> function, use the <code>fetch</code> API to send a request to your backend, capture the returned data, and update the <code>recipes</code> state.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSearchSubmit = <span class="hljs-keyword">async</span> (event: FormEvent) =&gt; {
  event.preventDefault();
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
      <span class="hljs-string">`http://localhost:5000/api/recipes/search?searchTerm=<span class="hljs-subst">${searchTerm}</span>`</span>
    );
    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    setRecipes(data.results);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
  }
};
</code></pre>
<h3 id="heading-step-5-display-recipe-data">Step 5: Display Recipe Data</h3>
<p>Create a new folder named <code>components</code> in your <code>src</code> directory. Inside this folder, create a file named <code>RecipeCard.tsx</code>. This component will display individual recipe data.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Recipe } <span class="hljs-keyword">from</span> <span class="hljs-string">"../types"</span>;

interface Props {
  <span class="hljs-attr">recipe</span>: Recipe;
}

<span class="hljs-keyword">const</span> RecipeCard = <span class="hljs-function">(<span class="hljs-params">{ recipe }: Props</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recipe-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{recipe.image}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recipe-card-title"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{recipe.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</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> RecipeCard;
</code></pre>
<p>Now, go back to <code>App.tsx</code> and import <code>RecipeCard</code>. Map over the <code>recipes</code> state to display each recipe using the <code>RecipeCard</code> component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> RecipeCard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/RecipeCard"</span>;

<span class="hljs-comment">// ... rest of the code</span>

<span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    {/* ... rest of the code */}
    {recipes.map((recipe) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">RecipeCard</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{recipe.id}</span> <span class="hljs-attr">recipe</span>=<span class="hljs-string">{recipe}</span> /&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>Now, when you submit a search term, the UI will display a list of recipe cards containing the images and titles of the recipes returned from the backend.</p>
<h3 id="heading-step-6-test-your-ui">Step 6: Test Your UI</h3>
<p>Run your React app, enter a search term such as "pasta" or "burgers", and submit the form. You should see a list of recipe cards displaying the relevant recipes from the backend.</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>Navigate to <code>http://localhost:3000</code> in your browser and try out your new recipe search UI!</p>
<h2 id="heading-how-to-build-the-pagination-and-view-more-functionality">How to Build the Pagination and View More Functionality</h2>
<h3 id="heading-step-1-backend-pagination">Step 1: Backend Pagination</h3>
<p>We added a <code>page</code> query parameter in the search endpoint. The <code>page</code> value is used to calculate the offset for the recipe data fetched from the database or external API.</p>
<h3 id="heading-step-2-add-view-more-button-to-the-ui">Step 2: Add "View More" Button to the UI</h3>
<p>Navigate to your <code>App.tsx</code> file. Scroll down to the JSX code where you map through the <code>recipes</code> array and add a "View More" button below it.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ... other code</span>
{
  recipes.map(<span class="hljs-function">(<span class="hljs-params">recipe</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RecipeCard</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{recipe.id}</span> <span class="hljs-attr">recipe</span>=<span class="hljs-string">{recipe}</span> /&gt;</span></span>);
}
&lt;button className=<span class="hljs-string">"view-more"</span> onClick={handleViewMoreClick}&gt;
  View More
&lt;/button&gt;;
<span class="hljs-comment">// ... other code</span>
</code></pre>
<h3 id="heading-step-3-create-a-useref-hook-to-store-the-current-page-number">Step 3: Create a <code>useRef</code> Hook to Store the Current Page Number</h3>
<p>Above your component's return statement, create a <code>useRef</code> hook to keep track of the current page number without causing re-renders.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ... other code</span>
<span class="hljs-keyword">const</span> pageNumber = useRef(<span class="hljs-number">1</span>);
<span class="hljs-comment">// ... other code</span>
</code></pre>
<h3 id="heading-step-4-implement-the-handleviewmoreclick-function">Step 4: Implement the <code>handleViewMoreClick</code> Function</h3>
<p>Define a function called <code>handleViewMoreClick</code> to handle the logic for loading more recipes.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ... other code</span>
<span class="hljs-keyword">const</span> handleViewMoreClick = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> nextPage = pageNumber.current + <span class="hljs-number">1</span>;
    <span class="hljs-keyword">const</span> nextRecipes = <span class="hljs-keyword">await</span> api.searchRecipes(searchTerm, nextPage);
    setRecipes(<span class="hljs-function">(<span class="hljs-params">prevRecipes</span>) =&gt;</span> [...prevRecipes, ...nextRecipes.results]);
    pageNumber.current = nextPage;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
  }
};
<span class="hljs-comment">// ... other code</span>
</code></pre>
<h3 id="heading-step-5-reset-page-number-on-new-search">Step 5: Reset Page Number on New Search</h3>
<p>Modify your <code>handleSearchSubmit</code> function to reset the page number back to 1 whenever a new search term is entered.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ... other code</span>
<span class="hljs-keyword">const</span> handleSearchSubmit = <span class="hljs-keyword">async</span> (event: FormEvent) =&gt; {
  <span class="hljs-comment">// ... other code</span>
  setRecipes(recipes.results);
  pageNumber.current = <span class="hljs-number">1</span>;
};
<span class="hljs-comment">// ... other code</span>
</code></pre>
<h3 id="heading-step-6-test-your-implementation">Step 6: Test Your Implementation</h3>
<p>Run your app and perform a search. Click the "View More" button to load more results. Change the search term and ensure that the page number resets, and you get a fresh list of recipes.</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>Now, as you search for recipes and click "View More," you should see additional recipes being loaded and displayed in the UI.</p>
<h2 id="heading-how-to-build-the-recipe-summary-modal-component">How to Build the Recipe Summary Modal Component</h2>
<p>I'll walk you through this process step-by-step. We'll create a model that displays a recipe summary using a specific endpoint from the provided API.</p>
<h3 id="heading-step-1-understanding-the-recipe-summary-endpoint">Step 1: Understanding the Recipe Summary Endpoint</h3>
<p>You can understand where the summary data comes from by looking at your API documentation. The endpoint you need is called <code>Summarize Recipe</code>. This endpoint requires a recipe ID to generate a summary.</p>
<h3 id="heading-step-2-setup-backend-endpoint">Step 2: Setup Backend Endpoint</h3>
<p>Create a backend endpoint that interfaces with the <code>Summarize Recipe</code> endpoint.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// In your backend, create an endpoint to fetch recipe summary</span>
<span class="hljs-comment">// File: recipe-api.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getRecipeSummary = <span class="hljs-keyword">async</span> (recipeId: <span class="hljs-built_in">string</span>) =&gt; {
  <span class="hljs-keyword">if</span> (!apiKey) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"API key not found"</span>);
  }

  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(
    <span class="hljs-string">`https://api.spoonacular.com/recipes/<span class="hljs-subst">${recipeId}</span>/summary`</span>
  );
  <span class="hljs-keyword">const</span> params = { apiKey: apiKey };
  url.search = <span class="hljs-keyword">new</span> URLSearchParams(params).toString();

  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url.toString());
  <span class="hljs-keyword">const</span> json = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">return</span> json;
};
</code></pre>
<h3 id="heading-step-3-create-a-backend-route">Step 3: Create a Backend Route</h3>
<p>Create a route in your backend to handle requests to your new endpoint.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// File: index.ts</span>
app.get(<span class="hljs-string">"/api/recipe/:recipeId/summary"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> recipeId = req.params.recipeId;
  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> recipeSummary(recipeId);
  res.json(result);
});
</code></pre>
<h3 id="heading-step-4-create-the-recipe-modal-component">Step 4: Create the Recipe Modal Component</h3>
<p>Create a React component for the recipe modal. We will use the useEffect hook to call the backend endpoint we just created, and store the Recipe Summary data in state.</p>
<p>First add a type for <code>RecipeSummary</code> to <code>types.ts</code></p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> RecipeSummary {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  summary: <span class="hljs-built_in">string</span>;
}
</code></pre>
<pre><code class="lang-jsx"><span class="hljs-comment">// File: RecipeModal.tsx</span>
<span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { RecipeSummary } <span class="hljs-keyword">from</span> <span class="hljs-string">"../types"</span>;

interface Props {
  <span class="hljs-attr">recipeId</span>: string;
  onClose: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">void</span>;
}

<span class="hljs-keyword">const</span> RecipeModal: React.FC&lt;Props&gt; = <span class="hljs-function">(<span class="hljs-params">{ recipeId, onClose }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [recipeSummary, setRecipeSummary] =
    (useState &lt; RecipeSummary) | (<span class="hljs-literal">null</span> &gt; <span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchRecipeSummary = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> summary = <span class="hljs-keyword">await</span> getRecipeSummary(recipeId);
        setRecipeSummary(summary);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error);
      }
    };
    fetchRecipeSummary();
  }, [recipeId]);

  <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">"overlay"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-content"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-header"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{recipeSummary?.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"close-button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClose}</span>&gt;</span>
              <span class="hljs-symbol">&amp;times;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">dangerouslySetInnerHTML</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">__html:</span> <span class="hljs-attr">recipeSummary</span>?<span class="hljs-attr">.summary</span> }} /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> RecipeModal;
</code></pre>
<h3 id="heading-step-5-style-the-modal">Step 5: Style the Modal</h3>
<p>Add the following CSS to style the modal:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* File: app.css */</span>
<span class="hljs-selector-class">.overlay</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.7</span>);
  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">1</span>;
}

<span class="hljs-selector-class">.modal</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);
  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">2</span>;
  <span class="hljs-attribute">background-color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>;
}

<span class="hljs-selector-class">.modal-header</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: row;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: space-between;
}
</code></pre>
<h3 id="heading-step-6-render-and-handle-modal-interactions">Step 6: Render and Handle Modal Interactions</h3>
<p>Modify your main component to handle rendering and interactions with the modal.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// File: App.tsx</span>
<span class="hljs-keyword">const</span> App: React.FC = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [selectedRecipe, setSelectedRecipe] =
    (useState &lt; Recipe) | (<span class="hljs-literal">undefined</span> &gt; <span class="hljs-literal">undefined</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      {/* Other components and logic */}
      {selectedRecipe &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">RecipeModal</span>
          <span class="hljs-attr">recipeId</span>=<span class="hljs-string">{selectedRecipe.id.toString()}</span>
          <span class="hljs-attr">onClose</span>=<span class="hljs-string">{()</span> =&gt;</span> setSelectedRecipe(undefined)}
        /&gt;
      )}
    <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>Now, when a user clicks on a recipe, the modal will appear displaying the summary of the selected recipe. The modal can be closed by clicking the close button, which will set the <code>selectedRecipe</code> back to undefined, hiding the modal.</p>
<h2 id="heading-how-to-create-endpoints-to-getcreatedelete-favorite-recipes">How to Create Endpoints to Get/Create/Delete Favorite Recipes</h2>
<h3 id="heading-step-1-setup-the-database">Step 1: Setup the Database</h3>
<p>First, we need to extend our database schema to include a table for storing favorite recipes by their IDs.</p>
<p>First, navigate to the <code>Prisma</code> folder within the <code>backend</code> directory of your project. Then open the <code>schema.prisma</code> file.</p>
<p>Define a new model for favorite recipes as follows:</p>
<pre><code class="lang-prisma">model FavoriteRecipe {
  id        Int    @id @default(autoincrement())
  recipeId  Int    @unique
}
</code></pre>
<h3 id="heading-step-2-synchronize-the-database-schema">Step 2: Synchronize the Database Schema</h3>
<p>Now, let's synchronize the updated schema with our database.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> backend
npx prisma db push
</code></pre>
<h3 id="heading-step-3-setup-the-endpoints">Step 3: Setup the Endpoints</h3>
<p>We need to set up endpoints in our Node backend to handle creating, viewing, and deleting favorites. We'll use the prismaClient to help us perform crud operations on the database.</p>
<p>First, we'll create a new post endpoint like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In backend/index.ts</span>
<span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;

<span class="hljs-keyword">const</span> prismaClient = <span class="hljs-keyword">new</span> PrismaClient();

app.post(<span class="hljs-string">"/api/recipes/favorite"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { recipeId } = req.body;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> favoriteRecipe = <span class="hljs-keyword">await</span> prismaClient.favoriteRecipe.create({
      <span class="hljs-attr">data</span>: { recipeId },
    });
    res.status(<span class="hljs-number">201</span>).json(favoriteRecipe);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Oops, something went wrong."</span> });
  }
});
</code></pre>
<p>Next, we'll create the View endpoint. To do that, create a utility function to fetch recipe details by IDs:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In backend/src/recipe-api.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getFavoriteRecipesByIds = <span class="hljs-keyword">async</span> (ids: string[]) =&gt; {
  <span class="hljs-keyword">if</span> (!apiKey) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"API Key not found"</span>);
  }
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"https://api.spoonacular.com/recipes/informationBulk"</span>);
  url.search = <span class="hljs-keyword">new</span> URLSearchParams({
    <span class="hljs-attr">apiKey</span>: apiKey,
    <span class="hljs-attr">ids</span>: ids.join(<span class="hljs-string">","</span>),
  }).toString();

  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url);
  <span class="hljs-keyword">const</span> json = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">results</span>: json };
};
</code></pre>
<p>Now, create the endpoint to fetch all favorite recipes:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In backend/index.ts</span>
<span class="hljs-keyword">import</span> { getFavoriteRecipesByIds } <span class="hljs-keyword">from</span> <span class="hljs-string">"./src/recipe-api"</span>;

app.get(<span class="hljs-string">"/api/recipes/favorite"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> favoriteRecipes = <span class="hljs-keyword">await</span> prismaClient.favoriteRecipe.findMany();
    <span class="hljs-keyword">const</span> recipeIds = favoriteRecipes.map(<span class="hljs-function">(<span class="hljs-params">recipe</span>) =&gt;</span>
      recipe.recipeId.toString()
    );
    <span class="hljs-keyword">const</span> favorites = <span class="hljs-keyword">await</span> getFavoriteRecipesByIds(recipeIds);
    res.json(favorites);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Oops, something went wrong."</span> });
  }
});
</code></pre>
<p>Next up is the Delete endpoint:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In backend/index.ts</span>
app.delete(<span class="hljs-string">"/api/recipes/favorite"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { recipeId } = req.body;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> prismaClient.favoriteRecipe.delete({
      <span class="hljs-attr">where</span>: { recipeId },
    });
    res.status(<span class="hljs-number">204</span>).send();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Oops, something went wrong."</span> });
  }
});
</code></pre>
<h3 id="heading-step-4-test-the-endpoints">Step 4: Test the Endpoints</h3>
<p>You can use tools like Postman or Thunder Client to test the endpoints. Make sure to adjust the request method and URL accordingly, and provide the necessary request body or parameters.</p>
<ul>
<li><strong>Creating a Favorite:</strong> POST request to <code>/api/recipes/favorite</code> with <code>recipeId</code> in the body.</li>
<li><strong>Viewing Favorites:</strong> GET request to <code>/api/recipes/favorite</code>.</li>
<li><strong>Deleting a Favorite:</strong> DELETE request to <code>/api/recipes/favorite</code> with <code>recipeId</code> in the body.</li>
</ul>
<h3 id="heading-step-5-verify-the-database">Step 5: Verify the Database</h3>
<p>Check the <code>favoriteRecipes</code> table in your ElephantSQL database to verify the actions performed through the endpoints.</p>
<h2 id="heading-how-to-add-favorites-functionality-to-the-frontend">How to Add Favorites Functionality to the Frontend</h2>
<h3 id="heading-step-1-setup-the-tab-functionality">Step 1: Setup the Tab Functionality</h3>
<p>Next, we'll look at how to integrate these endpoints on the frontend. We'll start by setting up tabs for 'Search' and 'Favorites' in our app.</p>
<p>First, define a new state to keep track of the selected tab.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

type Tabs = <span class="hljs-string">"search"</span> | <span class="hljs-string">"favorites"</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> [selectedTab, setSelectedTab] = useState &lt; Tabs &gt; <span class="hljs-string">"search"</span>;

  <span class="hljs-comment">// Rest of your code...</span>
}
</code></pre>
<h3 id="heading-step-2-render-tabs">Step 2: Render Tabs</h3>
<p>Now you'll render tabs in your JSX, and handle tab switching with the <code>onClick</code> event. This makes each <code>&lt;h1&gt;</code> element is clickable, and saves the tab the user clicked on in state. This helps conditionally render different UI elements depending on their selection.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Inside your JSX...</span>
&lt;div className=<span class="hljs-string">"tabs"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSelectedTab("search")}&gt;Recipe Search<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSelectedTab("favorites")}&gt;Favorites<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<h3 id="heading-step-3-conditional-rendering">Step 3: Conditional Rendering</h3>
<p>Based on the selected tab, you want to conditionally render either the search component or the favorites component. This will show/hide either the "search section" or the "favourites" section depending on the <code>selectedTab</code> state variable.</p>
<pre><code class="lang-jsx">{selectedTab === <span class="hljs-string">'search'</span> &amp;&amp; (
  <span class="hljs-comment">// search component code...</span>
)}
{selectedTab === <span class="hljs-string">'favorites'</span> &amp;&amp; (
  <span class="hljs-comment">// favorites component code...</span>
)}
</code></pre>
<h3 id="heading-step-4-fetch-favorite-recipes">Step 4: Fetch Favorite Recipes</h3>
<p>Next we need to populate the Favorite recipes tab with our favourite recipes. We want to do this when the App loads, for a quick user experience.</p>
<p>To do this, fetch the favorite recipes from the backend when the app loads using the <code>useEffect</code> hook, and store the fetched favorite recipes in a new state.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// api.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getFavouriteRecipes = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"http://localhost:5000/api/recipes/favourite"</span>);
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url);

  <span class="hljs-keyword">if</span> (!response.ok) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! Status: <span class="hljs-subst">${response.status}</span>`</span>);
  }
  <span class="hljs-keyword">return</span> response.json();
};
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">//App.tsx</span>
<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-comment">// ... Rest of your imports and code</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// ... Rest of your state declarations</span>

  <span class="hljs-keyword">const</span> [favoriteRecipes, setFavoriteRecipes] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchFavoriteRecipes = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> favouriteRecipes = <span class="hljs-keyword">await</span> api.getFavouriteRecipes();
        setFavouriteRecipes(favouriteRecipes.results);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error);
      }
    };

    fetchFavoriteRecipes();
  }, []);

  <span class="hljs-comment">// ... Rest of your code</span>
}
</code></pre>
<h3 id="heading-step-5-render-favorite-recipes">Step 5: Render Favorite Recipes</h3>
<p>Now you need to render the favorite recipes in the 'Favorites' tab.</p>
<pre><code class="lang-jsx">{selectedTab === <span class="hljs-string">'favorites'</span> &amp;&amp; (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    {favoriteRecipes.map(recipe =&gt; (
      // Render each favorite recipe card...
    ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)}
</code></pre>
<h3 id="heading-step-6-add-a-heart-icon">Step 6: Add a Heart Icon</h3>
<p>Next we'll add a way for the user to add and remove favorites. We'll do this by adding a "heart" icon to each card. </p>
<p>Before diving into the code, ensure you are in the correct directory by navigating to your project's front-end directory in your terminal. Install the necessary package for icons by running:</p>
<pre><code class="lang-bash">npm install react-icons
</code></pre>
<h3 id="heading-step-7-import-the-icon">Step 7: Import the Icon</h3>
<p>Open the <code>RecipeCard</code> component, and import the heart icon at the top of your file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { AiOutlineHeart } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-icons/ai"</span>;
</code></pre>
<h3 id="heading-step-8-insert-the-icon">Step 8: Insert the icon</h3>
<p>In the <code>RecipeCard</code> component, add the heart icon within a <code>span</code> element just above the <code>h3</code> tag:</p>
<pre><code class="lang-javascript">&lt;span onClick={handleFavoriteClick}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AiOutlineHeart</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span> /&gt;</span></span>
&lt;/span&gt;
</code></pre>
<h3 id="heading-step-9-add-css-styling">Step 9: Add CSS Styling</h3>
<p>In your <code>App.css</code> file, add the following CSS to style the icon and ensure it appears on the same line as the title. Using <code>flex</code> and <code>align-items</code> means the icon and title will be aligned nicely beneath the image:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.recipe-card-title</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">0.5rem</span>;
}
</code></pre>
<h3 id="heading-step-10-create-an-add-favourite-event-handler">Step 10: Create an Add Favourite Event Handler</h3>
<p>In <code>App.tsx</code>, create an event handler for favoriting a recipe. This is what will get called when the user clicks the heart icon on an recipe that hasn't yet been favorited:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> addfavoriteRecipe = <span class="hljs-keyword">async</span> (recipe) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> API.addFavoriteRecipe(recipe);
    setFavoriteRecipes([...favoriteRecipes, recipe]);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};
</code></pre>
<h3 id="heading-step-11-api-logic">Step 11: API Logic</h3>
<p>In a new file called <code>API.ts</code>, create a function to handle the API call to save a favorite recipe. This will call our endpoint which we created earlier in the backend:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addFavoriteRecipe = <span class="hljs-keyword">async</span> (recipe) =&gt; {
  <span class="hljs-keyword">const</span> body = {
    <span class="hljs-attr">recipeId</span>: recipe.id,
  };
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/recipes/favourite"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(body),
  });
  <span class="hljs-keyword">if</span> (!response.ok) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to save favorite"</span>);
  }
};
</code></pre>
<h3 id="heading-step-12-hook-up-the-event-handler">Step 12: Hook Up the Event Handler</h3>
<p>Pass the event handler to the <code>RecipeCard</code> component:</p>
<pre><code class="lang-javascript">&lt;RecipeCard
  <span class="hljs-comment">//.. other props</span>
  onFavoriteButtonClick={favoriteRecipe}
/&gt;
</code></pre>
<h3 id="heading-step-13-create-the-remove-favorite-event-handler">Step 13: Create the Remove Favorite Event Handler</h3>
<p>Similarly, create an event handler for un-favoriting a recipe in <code>App.tsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> removeFavoriteRecipe = <span class="hljs-keyword">async</span> (recipe) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> API.removeFavoriteRecipe(recipe);
    <span class="hljs-keyword">const</span> updatedRecipes = favoriteRecipes.filter(
      <span class="hljs-function">(<span class="hljs-params">favRecipe</span>) =&gt;</span> favRecipe.id !== recipe.id
    );
    setFavoriteRecipes(updatedRecipes);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};
</code></pre>
<h3 id="heading-step-14-api-logic">Step 14: API Logic</h3>
<p>In <code>API.ts</code>, create a function to handle the API call to remove a favorite recipe. Again, this will call the backend API to remove a recipe which we created earlier:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> removeFavoriteRecipe = <span class="hljs-keyword">async</span> (recipe) =&gt; {
  <span class="hljs-keyword">const</span> body = {
    <span class="hljs-attr">recipeID</span>: recipe.id,
  };
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/recipes/favourite"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"DELETE"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(body),
  });
  <span class="hljs-keyword">if</span> (!response.ok) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to remove favorite"</span>);
  }
};
</code></pre>
<h3 id="heading-step-15-conditional-event-handler">Step 15: Conditional Event Handler</h3>
<p>Depending on if the user is "favoriting" or "unfavoriting" a recipe, we want to conditionally call either <code>addFavoriteRecipe</code> or <code>removeFavoriteRecipe</code> based on the favorited state:</p>
<pre><code class="lang-javascript">&lt;RecipeCard
  <span class="hljs-comment">//.. other props</span>
  onFavoriteButtonClick={isFavorite ? removeFavoriteRecipe : favoriteRecipe}
/&gt;
</code></pre>
<h3 id="heading-step-16-determine-the-favorited-state">Step 16: Determine the Favorited State</h3>
<p>Before we can display the heart icon a favorited/non-favorited state, we need to know if the recipe is already a or not.   </p>
<p>To do this, we determine whether a recipe is favorited by checking if it exists in the <code>favoriteRecipes</code> state array. Pass this information to <code>RecipeCard</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> isFavorite = favoriteRecipes.some(
  <span class="hljs-function">(<span class="hljs-params">favRecipe</span>) =&gt;</span> favRecipe.id === recipe.id
);
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RecipeCard</span>
  // <span class="hljs-attr">...other</span> <span class="hljs-attr">props</span>
  <span class="hljs-attr">isFavorite</span>=<span class="hljs-string">{isFavorite}</span>
/&gt;</span></span>;
</code></pre>
<h3 id="heading-step-17-display-the-favorited-state">Step 17: Display the Favorited State</h3>
<p>In <code>RecipeCard</code>, conditionally render a filled or outlined heart icon based on the <code>isFavorite</code> prop:</p>
<pre><code class="lang-javascript">{
  isFavorite ? (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AiFillHeart</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"red"</span> /&gt;</span></span>
  ) : (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AiOutlineHeart</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span> /&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-how-to-add-cssstyling">How to Add CSS/Styling</h2>
<h3 id="heading-step-1-prepare-the-hero-image">Step 1: Prepare the Hero Image</h3>
<p>We've added some basic styling so far, so lets complete the CSS so that our app looks polished!</p>
<p>Firstly obtain an image from a source like <a target="_blank" href="https://www.pexels.com">Pexels</a> or any other image repository. This will be used in the Hero section of our app at the top, and will have our title overlaid on it. Ensure the image has a horizontal orientation for better handling of aspect ratios.</p>
<p>Place the image in the <code>public</code> folder of your project.</p>
<pre><code class="lang-plaintext">project-folder
│
└───public
    │   hero-image.jpeg
</code></pre>
<h3 id="heading-step-2-structure-the-header">Step 2: Structure the Header</h3>
<p>Open <code>app.tsx</code> and locate the JSX markup. Add a <code>className</code> of <code>app-container</code> to the top <code>div</code> element.</p>
<p>Inside the <code>app-container</code> div, add a new <code>div</code> with a <code>className</code> of <code>header</code>. Within the <code>header</code> div, add an <code>img</code> element with a <code>src</code> attribute pointing to your image, and a <code>div</code> element with a <code>className</code> of <code>title</code> containing the app's title.</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"app-container"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/hero-image.jpeg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Hero"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"title"</span>&gt;</span>My Recipe App<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  {<span class="hljs-comment">/* ...rest of your code */</span>}
&lt;/div&gt;
</code></pre>
<h3 id="heading-step-3-style-the-header">Step 3: Style the Header</h3>
<p>Open <code>app.css</code> and scroll to the top. Add the following CSS to style the <code>app-container</code>, <code>header</code>, <code>img</code>, and <code>title</code> elements. This makes the <code>title</code> appear on top of the image, with a translucent background:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.app-container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2em</span>;
}

<span class="hljs-selector-class">.header</span> {
  <span class="hljs-attribute">position</span>: relative;
}

<span class="hljs-selector-class">.header</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">object-fit</span>: cover;
  <span class="hljs-attribute">object-position</span>: center;
  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.5</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1em</span>;
}

<span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">background-color</span>: black;
  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.8</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5em</span> <span class="hljs-number">1.5em</span> <span class="hljs-number">0.5em</span> <span class="hljs-number">1.5em</span>;
}
</code></pre>
<h3 id="heading-step-4-adjust-the-layout">Step 4: Adjust the Layout</h3>
<p>Add padding to the <code>body</code> element and use a media query to add margins on larger screens. We do this so our app doesn't appear to narrow on mobile devices. When the screen size reaches <code>768px</code>, the media query will kick in and add margin to the left and right of our app, so that the app doesn't appear too wide.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5em</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f0f0f0</span>; <span class="hljs-comment">/* or any color you prefer */</span>
}

<span class="hljs-keyword">@media</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">10em</span>;
    <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">10em</span>;
  }
}
</code></pre>
<h3 id="heading-step-5-style-tabs-underline">Step 5: Style Tabs Underline</h3>
<p>Currently its not clear which tab the user has selected. What we want to do is add an orange underline to the selected tab. To do this, we can use a combination of CSS classes and conditional rendering.</p>
<p>Within <code>app.tsx</code>, locate your <code>h1</code> elements representing tabs, and dynamically apply a <code>className</code> of <code>tab-active</code> based on the selected tab.</p>
<pre><code class="lang-jsx">&lt;h1 className={selectedTab === <span class="hljs-string">'search'</span> ? <span class="hljs-string">'tab-active'</span> : <span class="hljs-string">''</span>}&gt;Search&lt;/h1&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{selectedTab</span> === <span class="hljs-string">'favorites'</span> ? '<span class="hljs-attr">tab-active</span>' <span class="hljs-attr">:</span> ''}&gt;</span>Favorites<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>In <code>app.css</code>, define the <code>tab-active</code> class:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.tab-active</span> {
  <span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">4px</span> solid orange; <span class="hljs-comment">/* or any color you prefer */</span>
  <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">0.5em</span>;
}
</code></pre>
<h3 id="heading-step-6-style-the-search-bar">Step 6: Style the Search Bar</h3>
<p>We want our search bar to take up the width of the container, and we want to add an icon instead of the search button, which makes our UI more interesting. </p>
<p>In <code>app.tsx</code>, locate the <code>form</code> element within the <code>Search</code> tab. Replace the text "Submit" in the <code>button</code> element with an icon from a library like React Icons.</p>
<pre><code class="lang-jsx">&lt;button&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AiOutlineSearch</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{40}</span> /&gt;</span></span>
&lt;/button&gt;
</code></pre>
<p>In <code>app.css</code>, style the <code>form</code>, <code>input</code>, and <code>button</code> elements:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">form</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">background-color</span>: white;
  <span class="hljs-attribute">align-items</span>: center;
}

<span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5em</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border</span>: none;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:focus</span> {
  <span class="hljs-attribute">outline</span>: none;
}

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">background-color</span>: white;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<h3 id="heading-step-7-implement-a-responsive-recipe-card-grid">Step 7: Implement a Responsive Recipe Card Grid</h3>
<p>Currently our Recipe Cards are stacked horizontally. We'll use CSS grid to make the recipe cards appear in a grid layout, which will also make things more responsive. </p>
<p>Within <code>app.tsx</code>, create a new <code>div</code> with a <code>className</code> of <code>recipe-grid</code> just above where you map over your recipes, and place the logic to rendering the recipes inside this <code>div</code>.</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"recipe-grid"</span>&gt;
  {recipes.map(<span class="hljs-function">(<span class="hljs-params">recipe</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> isFavourite = favouriteRecipes.some(<span class="hljs-function">(<span class="hljs-params">favRecipe</span>) =&gt;</span> favRecipe.id === recipe.id);

    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RecipeCard</span>
        <span class="hljs-attr">key</span>=<span class="hljs-string">{recipe.id}</span>
        <span class="hljs-attr">recipe</span>=<span class="hljs-string">{recipe}</span>
        <span class="hljs-attr">onFavouriteButtonClick</span>=<span class="hljs-string">{isFavourite</span> ? <span class="hljs-attr">removeFavouriteRecipe</span> <span class="hljs-attr">:</span> <span class="hljs-attr">addFavouriteRecipe</span>}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSelectedRecipe(recipe)}
        isFavourite={isFavourite}
      /&gt;</span>
    );
  })}
&lt;/div&gt;
</code></pre>
<p>In <code>app.css</code>, style the <code>recipe-grid</code> and <code>recipe-card</code> elements:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.recipe-grid</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(auto-fill, minmax(<span class="hljs-number">400px</span>, <span class="hljs-number">1</span>fr));
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2em</span>;
}

<span class="hljs-selector-class">.recipe-card</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">justify-content</span>: space-evenly;
  <span class="hljs-attribute">background-color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">4px</span> <span class="hljs-number">12px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">cursor</span>: pointer;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">1.5em</span>;
}

<span class="hljs-selector-class">.recipe-card</span> <span class="hljs-selector-tag">h3</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">white-space</span>: nowrap;
  <span class="hljs-attribute">overflow</span>: hidden;
  <span class="hljs-attribute">text-overflow</span>: ellipsis;
}
</code></pre>
<h3 id="heading-step-8-final-touches">Step 8: Final Touches</h3>
<p>Style the "View More" button to make sure it matches the style of our app, and is centered beneath our recipe grid:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.view-more-button</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">margin</span>: auto;
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congrats on making it to the end! Hopefully you've learned a few things about full stack development using React and Node. </p>
<p>If you enjoyed this project, you can find more at <a target="_blank" href="https://www.codecoyotes.com/">CodeCoyotes.com</a>, where you can also send me a message if you need to get in contact.   </p>
<p>Thanks for reading, see you in the next one!  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Full Stack Project Tutorial – Create A Notes App Using React and Node.js ]]>
                </title>
                <description>
                    <![CDATA[ Hey there! Ready to build something cool? In this tutorial, we're going to create a full stack notes app using React, Node.js, and PostgreSQL.  We'll start from scratch and end up with a fully functioning app where you can create, edit, and delete no... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/full-stack-project-tutorial-create-a-notes-app-using-react-and-node-js/</link>
                <guid isPermaLink="false">66c8c8d7fe21816c4cb75d17</guid>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ postgres ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Thu, 28 Sep 2023 14:10:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/react-node-notes-app-screenshot-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hey there! Ready to build something cool? In this tutorial, we're going to create a full stack notes app using React, Node.js, and PostgreSQL. </p>
<p>We'll start from scratch and end up with a fully functioning app where you can create, edit, and delete notes. Plus, we're adding validation on both the UI and the backend to keep things in check!</p>
<p>This guide is all about giving you the real-deal experience of building a web app. You'll get to learn how each piece of the puzzle fits together – from the front-end magic with React, to the server-side wonders with Node.js, and storing all the good stuff in a PostgreSQL database. And hey, we're making sure it looks good and works well on mobile screens too!</p>
<p>By the end of this, you’ll have a good grip on full stack development with React and Node, which you can carry with you into future projects. It’s all about learning by doing, and getting the skills to make your ideas come to life. So, grab a cup of coffee, roll up your sleeves, and let’s get coding!</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Since we will be focusing on how to build a project, there are a few prerequisites that will be needed to get the most out of this tutorial:</p>
<ul>
<li>Some knowledge about web development concepts (frontend, backend, databases, API's, REST).</li>
<li>Some knowledge of JavaScript (variables, functions, objects, arrays, and so on).</li>
<li>Basic understanding on React (how to create components, add styles, work with state).</li>
<li>Basic understanding on Node.js/Express (working with APIs).</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-well-build">What We'll Build</a></li>
<li><a class="post-section-overview" href="#heading-challenge-try-it-yourself-first">Challenge: Try it Yourself First!</a></li>
<li><a class="post-section-overview" href="#heading-video-tutorial">Video Tutorial</a></li>
<li><a class="post-section-overview" href="#heading-part-1-create-the-ui">PART 1 – Create the UI</a></li>
<li><a class="post-section-overview" href="#heading-part-2-create-the-backend">PART 2 - Create the Backend</a></li>
<li><a class="post-section-overview" href="#heading-part-3-connect-ui-to-backend">PART 3 - Connect UI to Backend</a></li>
<li><a class="post-section-overview" href="#heading-the-end-why-not-try-the-bonus-challenges">The End - Why not try the bonus challenges?</a></li>
</ul>
<h2 id="heading-what-well-build">What We'll Build</h2>
<p>In this tutorial, we'll build a full stack notes app from scratch, using React, Node.js and PostgreSQL, with the following features:</p>
<ul>
<li>Create/Edit/Delete Notes</li>
<li>Validation on the UI and Backend</li>
<li>Responsive on mobile screens</li>
</ul>
<h2 id="heading-challenge-try-it-yourself-first">Challenge: Try it Yourself First!</h2>
<p>If you would like to attempt this project yourself first without looking at the tutorial, here's a few hints:</p>
<ul>
<li>Tackle one little piece at a time. For example, you would focus on getting the UI working on the UI first, and tackle the APIs later.</li>
<li>Think about your data – What do you need to store? What data structure (for example, arrays) will you use to return the data via the API?  How will you render this data on the UI?</li>
<li>Don't forget about validation and error handling. What will happen if the user tries to save a note without a title field? How will you prevent this? (Hint: Forms and the <code>required</code> field will be your friend here)</li>
<li>Remember there is no perfect way to complete a project. The tutorial below is one way to tackle the problem. You can choose to go a different way, putting your own unique style on things. The main thing is that you start!</li>
</ul>
<p>If you need more help on getting started yourself, you can find more hints and tips, starter code, and completed code you can reference over at <a target="_blank" href="https://www.codecoyotes.com/projects/react-node-notes-app">codecoyotes.com</a>.</p>
<h2 id="heading-video-tutorial">Video Tutorial</h2>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/2MoSzSlAuNk" 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>
<h2 id="heading-part-1-create-the-ui">PART 1 – Create the UI</h2>
<p>We'll start this tutorial by creating the UI using some mock data. This lets us focus on our styling, and how things to look, without having to worry about creating a backend right away.</p>
<h3 id="heading-create-a-new-react-app">Create a New React App</h3>
<p>Okay, first things first: let's set up our project structure. Open your terminal and navigate to your desktop. Our next step is to create a new folder that will hold both our UI and backend code. Let's name it <code>notes-app</code>:</p>
<pre><code class="lang-bash">mkdir notes-app
</code></pre>
<p>Once that's done, navigate into the newly created <code>notes-app</code> directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> notes-app
</code></pre>
<p>Next, we'll create a new React app using TypeScript as our template. We'll use the <code>npx create-react-app</code> command for this, specifying TypeScript as the template:</p>
<pre><code class="lang-bash">npx create-react-app notes-app --template typescript
</code></pre>
<p>After you hit Enter, the process may take a few minutes to install all necessary packages. Once it's completed, open the <code>notes-app</code> folder in Visual Studio Code or your preferred IDE.</p>
<p>In Visual Studio Code, you should see that the <code>notes-app</code> is at the top level of your directory. As the course progresses, we will add a <code>notes-app-server</code> directory as well to keep all the code together in one place.</p>
<p>Now open a new terminal within your IDE and navigate to your React app's directory (let's assume you named it <code>notes-app</code>):</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> notes-app
</code></pre>
<p>Then, run the following command to start the front-end development server:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>If all goes well, your browser will automatically open and display your new React app. You should see a spinning React logo, among other default assets.</p>
<p>Finally, let's clear out the boilerplate code to have a clean starting point for our app. Open <code>src/App.tsx</code> in your IDE and delete its content. This will be our new starting point for building the app.</p>
<h3 id="heading-add-ui-elements">Add UI Elements</h3>
<p>Okay, the first thing we'll do is put some of our UI components in place. This will consist of the general markup and CSS, without involving any JavaScript. This gives us a glimpse of how we envision the layout, without having to concern ourselves with API calls or database interactions at this stage.</p>
<p>We'll navigate to <code>.App.tsx</code> and create a new component. Make sure to import our stylesheet from <code>App.css</code>. The first thing to add is a <code>div</code> with a class name of <code>AppContainer</code>. This will help position our form and the CSS grid for our notes.</p>
<p>Within this <code>div</code>, we'll include our form tags. Here, we'll add an input field for the title — this is where the user can enter the note title. We'll also include a textarea for the note content. Both of these fields will be set to <code>required</code>, enabling browser-native validation messages if the user tries to submit an incomplete form. </p>
<p>At the bottom of the form, we'll include a button of type <code>submit</code>, which will handle form submissions when clicked.</p>
<p>Off to the right, we'll add a <code>div</code> to contain our notes. This will be structured as a CSS grid. Initially, we'll populate this grid with a single note to see how it looks.</p>
<p>For our note, we'll have a header containing a delete button situated on the right-hand side. We'll display the user-entered title – for demonstration purposes, we're using a dummy title. We'll also include the content that the user entered.</p>
<p>Finally, we'll export our component at the very bottom.</p>
<h3 id="heading-completed-code-for-this-section">Completed code for this section</h3>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app-container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"note-form"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Title"</span> <span class="hljs-attr">required</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Content"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">{10}</span> <span class="hljs-attr">required</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>Add Note<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 class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"notes-grid"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"note-item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"notes-header"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>x<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">h2</span>&gt;</span>Note Title<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Note content<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-add-css">Add CSS</h3>
<h4 id="heading-start-the-app">Start the App</h4>
<p>First, let's open a terminal and type <code>npm start</code>. This will launch the app in the browser. As you can see on the right-hand side, the appearance isn't great yet. This is because we haven't applied any styles. To fix this, we'll navigate to <code>App.css</code> and style the classes we added earlier.</p>
<p>You can download the styles from the link in the description if you prefer to copy and paste. Alternatively, feel free to follow along with the video and pause as needed. Remember, these styles are just examples for learning – they don't have to be perfect.</p>
<h4 id="heading-style-the-body-and-app-container">Style the Body and App Container</h4>
<p>In <code>App.css</code>, the first thing we'll do is add some styles to the <code>body</code>. We'll give it a gray background and a margin to prevent the app from touching the browser window edges. Next, we'll style our <code>App Container</code>.</p>
<p>We're designing this mobile-first, meaning the default styles will target mobile screens. We'll use media queries for larger displays. This approach is optional, but often it's easier to start with mobile designs.</p>
<p>For mobile screens, we want our <code>App Container</code> to default to a single column layout, stacking our form and notes grid on top of each other.</p>
<h4 id="heading-use-media-queries">Use Media Queries</h4>
<p>We'll add a media query specifying that for screens larger than 600 pixels, we'll use a two-column layout. We'll define this using <code>grid-template-columns</code>. </p>
<p>The first column will be 200 pixels wide, accommodating the form. The second column will use <code>1fr</code>, filling the remaining space. A 20-pixel gap will separate the two columns.</p>
<h4 id="heading-style-the-notes-grid">Style the Notes Grid</h4>
<p>Next, let's style our notes grid. We'll use CSS grid and define <code>grid-template-columns</code>. </p>
<p>Each grid item will have a minimum width of 250 pixels and can expand to fill available space. Don't worry if this sounds confusing – it will become clear soon.</p>
<p>We'll also set <code>grid-auto-rows</code> to ensure each row is a minimum of 250 pixels tall, accommodating notes of different sizes while maintaining a consistent row height.</p>
<h4 id="heading-style-individual-notes">Style Individual Notes</h4>
<p>For each note, we'll use Flexbox and set <code>flex-direction</code> to column, stacking the header, title, and content vertically. We'll also add some basic styles like border, padding, and background color. A box shadow will provide a finishing touch.</p>
<h4 id="heading-style-the-header-and-delete-button">Style the Header and Delete Button</h4>
<p>The header will also use Flexbox, and we'll set <code>justify-content</code> to <code>flex-end</code> to align the delete button to the right. The button will receive custom styles for a polished look.</p>
<h4 id="heading-style-the-form">Style the Form</h4>
<p>Lastly, we'll style the form on the left column. Again, we'll use Flexbox with a column layout and a 20-pixel gap between elements. The text area and input fields will get borders, padding, and resized fonts. We'll also style the submit button and add hover effects.</p>
<h4 id="heading-completed-code-for-this-section-1">Completed code for this section</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">background-color</span>: lightgrey;
}

<span class="hljs-selector-class">.app-container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr;
}

<span class="hljs-keyword">@media</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">600px</span>) {
  <span class="hljs-selector-class">.app-container</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">1</span>fr;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">20px</span>;
  }
}

<span class="hljs-selector-class">.notes-grid</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(auto-fill, minmax(<span class="hljs-number">250px</span>, <span class="hljs-number">1</span>fr));
  <span class="hljs-attribute">grid-auto-rows</span>: <span class="hljs-built_in">minmax</span>(<span class="hljs-number">250px</span>, auto);
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.note-item</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f9f9f9</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">0px</span> <span class="hljs-number">10px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.notes-header</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: flex-end;
}

<span class="hljs-selector-class">.notes-header</span> <span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">background</span>: transparent;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">cursor</span>: pointer;
  <span class="hljs-attribute">max-width</span>: fit-content;
}

<span class="hljs-selector-tag">h2</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.note-form</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-tag">textarea</span>,
<span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
}

<span class="hljs-selector-class">.note-form</span> <span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">64</span>, <span class="hljs-number">154</span>, <span class="hljs-number">184</span>);
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">color</span>: white;
}

<span class="hljs-selector-class">.note-form</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">106</span>, <span class="hljs-number">175</span>, <span class="hljs-number">198</span>);
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.edit-buttons</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-evenly;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-class">.edit-buttons</span> <span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
}

<span class="hljs-selector-class">.edit-buttons</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:last-of-type</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">220</span>, <span class="hljs-number">89</span>, <span class="hljs-number">89</span>);
  <span class="hljs-attribute">color</span>: white;
}
</code></pre>
<h3 id="heading-add-dummy-notes">Add Dummy Notes</h3>
<h4 id="heading-add-dummy-notes-for-css-grid-testing">Add Dummy Notes for CSS Grid Testing</h4>
<p>Now that we have our CSS in place, the next step is to add dummy notes to our <code>App</code> component to test the responsiveness of our CSS grid. To achieve this, we'll navigate to <code>App.tsx</code> and import the <code>useState</code> hook from React.</p>
<p>Inside our <code>App</code> component, we'll store the notes within the <code>useState</code> hook. Whenever you have UI elements that can change, it's a good idea to manage them in the state. We'll initialize this with a dummy array of notes, where each note has an <code>id</code>, a <code>title</code>, and <code>content</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [notes, setNotes] = useState&lt;Note[]&gt;([
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 1"</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note1"</span>,
},
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 2 "</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note2"</span>,
},
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 3"</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note3"</span>,
},
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 4 "</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note4"</span>,
},
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 5"</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note5"</span>,
},
{
  <span class="hljs-attr">id</span>: <span class="hljs-number">6</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"test note 6"</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">"bla bla note6"</span>,
},
]);
</code></pre>
<p>Think of this as simulating an API call and storing the returned data in the state. The structure of this data will be similar to what we'll receive from our API requests when we eventually build out our backend.</p>
<h4 id="heading-map-notes-to-components">Map Notes to Components</h4>
<p>With our array of notes in state, we can now use the <code>map</code> function within our notes grid to display the markup for each note. The <code>map</code> function will run as many times as there are notes in the array. Instead of hardcoding the <code>title</code> and <code>content</code>, we'll pull these values from each <code>note</code> object:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"notes-grid"</span>&gt;
  {notes.map(<span class="hljs-function">(<span class="hljs-params">note</span>) =&gt;</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">"note-item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"notes-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>x<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">h2</span>&gt;</span>{note.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{note.content}<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>
  ))}
&lt;/div&gt;
</code></pre>
<h4 id="heading-verify-responsiveness">Verify Responsiveness</h4>
<p>After these steps, you should see four notes displayed in the browser, populated with the values from the objects in the array.</p>
<p>To verify that our layout is responsive, you can change the window size. You'll see that the notes adjust based on the window size. When the window is at its smallest—simulating a mobile screen—the form will stack vertically above the notes grid.</p>
<h3 id="heading-save-note-form">Save Note Form</h3>
<p>Now that we have our UI set up, let's focus on adding functionality to the form that allows us to create a new note. Initially, we'll implement this for the UI. Later, we'll make the data persistent by linking it to the backend, which we'll build separately.</p>
<h4 id="heading-use-state-for-form-inputs-in-react">Use State for Form Inputs in React</h4>
<p>In React, when working with forms, it's a best practice to maintain a state variable for each form input. This enables React to control those inputs, making it easier to capture their values and use them programmatically.</p>
<p>In our code, we have two form inputs: one for the title and another for the content. For these, we'll set up two state variables called <code>title</code> and <code>content</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [title, setTitle] = useState(<span class="hljs-string">""</span>);
<span class="hljs-keyword">const</span> [content, setContent] = useState(<span class="hljs-string">""</span>);
</code></pre>
<p>For the title input, we bind its value to the <code>title</code> state variable and update this state whenever the user types into the field:</p>
<pre><code class="lang-javascript">&lt;input
  value={title}
  onChange={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> setTitle(event.target.value)}
  placeholder=<span class="hljs-string">"Title"</span>
  required
&gt;&lt;/input&gt;
</code></pre>
<p>Similarly, we'll handle the <code>textarea</code> for content:</p>
<pre><code class="lang-javascript">&lt;textarea
  value={content}
  onChange={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> setContent(event.target.value)}
  placeholder=<span class="hljs-string">"Content"</span>
  rows={<span class="hljs-number">10</span>}
  required
&gt;&lt;/textarea&gt;
</code></pre>
<h4 id="heading-handle-form-submission">Handle Form Submission</h4>
<p>After binding our form inputs to state variables, the next step is to add a function that handles the form submission. We'll name this function <code>handleAddNote</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleAddNote = <span class="hljs-function">(<span class="hljs-params">event: React.FormEvent</span>) =&gt;</span> {
  event.preventDefault();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"title: "</span>, title);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"content: "</span>, content);
};
</code></pre>
<p>In this function, we specify the parameter type as <code>React.FormEvent</code> to satisfy TypeScript's typing requirement. We also call <code>event.preventDefault()</code> to prevent the form from submitting and refreshing the page, which is its default behavior. Following that, we log the <code>title</code> and <code>content</code> state variables to the console.</p>
<p>Finally, we'll connect this function to the <code>onSubmit</code> event in our form:</p>
<pre><code class="lang-jsx">&lt;form onSubmit={handleAddNote}&gt;{<span class="hljs-comment">/* ...form inputs here... */</span>}&lt;/form&gt;
</code></pre>
<h4 id="heading-test-the-form">Test the Form</h4>
<p>To test this setup, open the browser console, input a title and some content, and click the "Add Note" button. You should see the title and content values logged in the console, confirming that our form is capturing input as expected.</p>
<h3 id="heading-handle-the-add-note-functionality">Handle the "Add Note" Functionality</h3>
<p>Now that we've set up our state variables for the title and content, we can proceed to implement the function that handles adding a new note. This function will create a new note object and add it to our <code>notes</code> array, thereby updating the UI.</p>
<h4 id="heading-create-a-new-note-object">Create a New Note Object</h4>
<p>First, let's create a new note object and specify its type as <code>Note</code>, taking advantage of TypeScript's type system:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> newNote: Note = {
  <span class="hljs-attr">id</span>: notes.length + <span class="hljs-number">1</span>,
  <span class="hljs-attr">title</span>: title,
  <span class="hljs-attr">content</span>: content,
};
</code></pre>
<p>Because we've explicitly typed our object, TypeScript's IntelliSense will assist us in populating the object, ensuring that we don't miss any required properties. For now, we'll set the <code>id</code> to the length of the current <code>notes</code> array plus one, although this <code>id</code> will eventually be generated by our backend database.</p>
<h4 id="heading-update-state-with-new-note">Update State with New Note</h4>
<p>Once we have our new note object, we need to update our <code>notes</code> state array. We'll use the <code>setNotes</code> function for this purpose:</p>
<pre><code class="lang-javascript">setNotes([newNote, ...notes]);
</code></pre>
<p>The new note object will be the first item in the new <code>notes</code> array, followed by the existing notes, which we'll spread into the new array using the spread operator. This effectively makes a copy of the old <code>notes</code> array and inserts it into the new one.</p>
<h4 id="heading-clear-the-form-inputs">Clear the Form Inputs</h4>
<p>Lastly, let's reset the <code>title</code> and <code>content</code> state variables to empty strings, improving the user experience by clearing the form once a note is added:</p>
<pre><code class="lang-javascript">setTitle(<span class="hljs-string">""</span>);
setContent(<span class="hljs-string">""</span>);
</code></pre>
<h4 id="heading-test-the-functionality">Test the Functionality</h4>
<p>And that's it! If you now go to the browser, input a title and some content, and then click "Add Note," you'll see your new note appear at the top of the list, and the form fields will be cleared, ready for a new entry.</p>
<h3 id="heading-handle-the-update-note-functionality">Handle the "Update Note" Functionality</h3>
<p>In this section, we'll focus on implementing the feature that allows users to update an existing note. When a user clicks on a note, we want to populate the <code>title</code> and <code>content</code> fields in our form with the note's existing values. We'll also add a "Save" and "Cancel" button.</p>
<h4 id="heading-cleanup-and-initial-setup">Cleanup and Initial Setup</h4>
<p>First, let's clean up our code by removing any <code>console.log</code> statements – they are no longer needed:</p>
<pre><code class="lang-tsx">const [selectedNote, setSelectedNote] = useState&lt;Note | null&gt;(null);
</code></pre>
<h4 id="heading-track-the-selected-note">Track the Selected Note</h4>
<p>To track which note the user has clicked on, we'll create a new state variable called <code>selectedNote</code>. This state variable will have a type of <code>Note</code> or <code>null</code> to account for the possibility that no note is selected. We'll initialize this state to <code>null</code>.</p>
<h4 id="heading-create-the-click-handler">Create the Click Handler</h4>
<p>Next, let's create a function named <code>handleNoteClick</code> to handle the user's click event on a note. This function will take a <code>note</code> object as its argument:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleNoteClick = <span class="hljs-function">(<span class="hljs-params">note: Note</span>) =&gt;</span> {
  setSelectedNote(note);
  setTitle(note.title);
  setContent(note.content);
};
</code></pre>
<p>Within this function, we'll use <code>setSelectedNote</code> to save the clicked note to our <code>selectedNote</code> state. Additionally, we'll populate the <code>title</code> and <code>content</code> state variables with the values from the clicked note.</p>
<h4 id="heading-update-the-ui">Update the UI</h4>
<p>In the JSX for rendering each note, add an <code>onClick</code> event to the top-level <code>div</code> element for each note. Call the <code>handleNoteClick</code> function and pass the <code>note</code> object to it:</p>
<pre><code class="lang-jsx">&lt;div key={note.id} className=<span class="hljs-string">"note-item"</span> onClick={<span class="hljs-function">() =&gt;</span> handleNoteClick(note)}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"notes-header"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>x<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="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{note.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{note.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>Since we are iterating over notes using the <code>map</code> function, this <code>onClick</code> handler will be added to each note automatically.</p>
<h4 id="heading-save-user-changes">Save user changes</h4>
<p>Now that we have the capability for the user to edit a note, we'll implement the functionality to save the changes they make to both the <code>title</code> and <code>content</code> of a note into our state.</p>
<h4 id="heading-the-handleupdatenote-function">The <code>handleUpdateNote</code> Function</h4>
<p>Let's create a new function called <code>handleUpdateNote</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleUpdateNote = <span class="hljs-function">(<span class="hljs-params">event: React.FormEvent</span>) =&gt;</span> {
  event.preventDefault();

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

  <span class="hljs-keyword">const</span> updatedNote: Note = {
    <span class="hljs-attr">id</span>: selectedNote.id,
    <span class="hljs-attr">title</span>: title,
    <span class="hljs-attr">content</span>: content,
  };

  <span class="hljs-keyword">const</span> updatedNotesList = notes.map(<span class="hljs-function">(<span class="hljs-params">note</span>) =&gt;</span> (note.id === selectedNote.id ? updatedNote : note));

  setNotes(updatedNotesList);
  setTitle(<span class="hljs-string">""</span>);
  setContent(<span class="hljs-string">""</span>);
  setSelectedNote(<span class="hljs-literal">null</span>);
};
</code></pre>
<p>Within this function, we use <code>event.preventDefault()</code> to prevent the form from automatically submitting when the "Save" button is clicked. We also validate if a note is selected. If not, we exit the function early to prevent potential errors.</p>
<p>Next, we form an updated note object based on the selected note's <code>id</code> and the updated <code>title</code> and <code>content</code>. After that, we utilize the <code>map</code> function to generate a new array of notes, replacing the selected note with our updated note where the <code>id</code> matches. The updated array is then set to our state using the <code>setNotes</code> function. Finally, we reset our <code>title</code>, <code>content</code>, and <code>selectedNote</code> state values to their initial states.</p>
<h4 id="heading-the-handlecancel-function">The <code>handleCancel</code> Function</h4>
<p>We'll also implement a simple <code>handleCancel</code> function to reset our form and selected note when the user decides not to proceed with an update:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleCancel = <span class="hljs-function">() =&gt;</span> {
  setTitle(<span class="hljs-string">""</span>);
  setContent(<span class="hljs-string">""</span>);
  setSelectedNote(<span class="hljs-literal">null</span>);
};
</code></pre>
<h4 id="heading-update-the-jsx">Update the JSX</h4>
<p>Let's introduce conditional rendering in our JSX to display the appropriate buttons based on whether a note is selected for editing or not:</p>
<pre><code class="lang-jsx">&lt;form
  className=<span class="hljs-string">"note-form"</span>
  onSubmit={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> (selectedNote ? handleUpdateNote(event) : handleAddNote(event))}
&gt;
  {<span class="hljs-comment">/* ... other form elements ... */</span>}
  {selectedNote ? (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"edit-buttons"</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>Save<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">{handleCancel}</span>&gt;</span>Cancel<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="xml"><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>Add Note<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  )}
&lt;/form&gt;
</code></pre>
<p>Within our form's <code>onSubmit</code> event, we've added a conditional. If a note is selected, we'll trigger the <code>handleUpdateNote</code> function. Otherwise, the <code>handleAddNote</code> function will be executed.</p>
<h4 id="heading-test-the-implementation">Test the Implementation</h4>
<p>After incorporating these changes, run your application. When you select a note, make modifications, and click on "Save", you'll observe the note gets updated.</p>
<h3 id="heading-delete-notes-from-the-ui">Delete Notes from the UI</h3>
<p>The last piece of functionality we need on the frontend before moving to the backend development is the ability to delete notes. You'll recall that we added a small "X" button to each note for this purpose. Clicking this button should remove the note from the UI. Let's jump back into the <code>App.tsx</code> file and implement this.</p>
<h4 id="heading-the-deletenote-function">The <code>deleteNote</code> Function</h4>
<p>First, create a function named <code>deleteNote</code> as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> deleteNote = <span class="hljs-function">(<span class="hljs-params">event: React.MouseEvent, noteId: number</span>) =&gt;</span> {
  event.stopPropagation();

  <span class="hljs-keyword">const</span> updatedNotes = notes.filter(<span class="hljs-function">(<span class="hljs-params">note</span>) =&gt;</span> note.id !== noteId);

  setNotes(updatedNotes);
};
</code></pre>
<p>This function takes in two parameters: the <code>event</code> object and the <code>noteId</code>. The <code>event.stopPropagation()</code> line is crucial here because the delete button is nested within a clickable note. It prevents the <code>deleteNote</code> event from interfering with the click event on the note itself. This is especially important when dealing with nested <code>onClick</code> events.</p>
<h4 id="heading-the-filtering-logic">The Filtering Logic</h4>
<p>The core of the delete functionality lies in the <code>filter</code> method applied to the <code>notes</code> array. This method loops through the array and applies a function to each element, much like the <code>map</code> method. It will only return the notes whose IDs do not match the <code>noteId</code> provided, effectively removing the selected note.</p>
<p>We save this newly filtered array into a variable called <code>updatedNotes</code> and then update our state with it by calling <code>setNotes(updatedNotes)</code>.</p>
<h4 id="heading-add-the-onclick-event">Add the <code>onClick</code> Event</h4>
<p>After defining the <code>deleteNote</code> function, attach it to the delete button within the note. Pass in the event and the note ID, like so:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> deleteNote(event, note.id)}&gt;x&lt;/button&gt;
</code></pre>
<h4 id="heading-test-the-functionality-1">Test the Functionality</h4>
<p>Now, if you run your app and click the delete button on a given note, you will observe that the note disappears from the UI.</p>
<h2 id="heading-part-2-create-the-backend">PART 2 - Create the Backend</h2>
<p>After implementing UI functionalities, it's time to set up a backend that allows us to persist notes when the user adds, edits, or deletes them. For this, create a new folder in your project at the top level and name it <code>notes-app-server</code>. Even though it might seem like the server code is in the same directory as the UI, they are entirely separate and will run independently.</p>
<h3 id="heading-initial-setup">Initial Setup</h3>
<ol>
<li>Open your terminal and navigate to the <code>notes-app-server</code> folder you just created.</li>
<li>Run the following commands:</li>
</ol>
<pre><code class="lang-bash">npm init
npm i ts-node typescript nodemon @types/cors @types/express @types/node --save-dev
npm i @prisma/client cors express prisma
npx tsc --init
</code></pre>
<ul>
<li><code>npm init</code>: Initializes a new npm module and gives you access to npm packages.</li>
<li><code>npm i ... --save-dev</code>: Installs development dependencies like TypeScript and type definitions.</li>
<li><code>npm i ...</code>: Installs production dependencies like Express and Prisma.</li>
</ul>
<h3 id="heading-modify-packagejson">Modify <code>package.json</code></h3>
<p>After running the above commands, navigate to your <code>package.json</code> and update the <code>scripts</code> section with:</p>
<pre><code class="lang-json"><span class="hljs-string">"start"</span>: <span class="hljs-string">"npx nodemon"</span>
</code></pre>
<p>This script uses nodemon for hot-reloading.</p>
<h3 id="heading-implement-the-server">Implement the Server</h3>
<p>Now, within the <code>notes-app-server</code> directory, create a <code>src</code> folder and within it, an <code>index.ts</code> file. Insert the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> cors <span class="hljs-keyword">from</span> <span class="hljs-string">"cors"</span>;

<span class="hljs-keyword">const</span> app = express();

app.use(express.json());
app.use(cors());

app.get(<span class="hljs-string">"/api/notes"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"success!"</span> });
});

app.listen(<span class="hljs-number">5000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"server running on localhost:5000"</span>);
});
</code></pre>
<ol>
<li><code>import express and cors</code>: We import the required libraries for our server.</li>
<li><code>const app = express();</code>: Initializes a new Express application.</li>
<li><code>app.use(express.json());</code>: Parses the JSON body from incoming API requests.</li>
<li><code>app.use(cors());</code>: Adds CORS support.</li>
<li><code>app.listen(5000, ...)</code>: This starts the server listening on port 5000.</li>
</ol>
<h3 id="heading-test">Test</h3>
<p>Finally, you can test the server by navigating to the <code>notes-app-server</code> directory in your terminal and running:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>You should see the console log: <code>server running on localhost:5000</code>. To further test, you can use a curl command to hit the <code>/api/notes</code> endpoint. If everything is set up correctly, you'll get a JSON object back.</p>
<h3 id="heading-create-a-postgres-database">Create a Postgres Database</h3>
<p>ElephantSQL is a PostgreSQL database hosting service that makes it easy to set up, maintain, and scale your PostgreSQL database. Here's how to get started with creating a database using ElephantSQL.</p>
<h4 id="heading-step-1-sign-up-log-in">Step 1: Sign Up / Log In</h4>
<ol>
<li>Navigate to the <a target="_blank" href="https://www.elephantsql.com/">ElephantSQL website</a>.</li>
<li>If you don't have an account, you can sign up for free. If you already have one, go ahead and log in.</li>
</ol>
<h4 id="heading-step-2-create-a-new-instance">Step 2: Create a New Instance</h4>
<ol>
<li>Once logged in, you'll find yourself on the "Dashboard" page.</li>
<li>Click on the "Create New Instance" button.</li>
<li>You'll be taken to a page where you can set the details for your new PostgreSQL database instance.</li>
</ol>
<h4 id="heading-step-3-choose-a-plan">Step 3: Choose a Plan</h4>
<ol>
<li>You can start with a free "Tiny Turtle" plan, which is perfect for small projects and testing.</li>
<li>Select the plan that best suits your needs and click "Select".</li>
</ol>
<h4 id="heading-step-4-configure-your-instance">Step 4: Configure Your Instance</h4>
<ol>
<li>You'll be asked to name your instance. Choose a name that you'll remember and that describes the purpose of the database.</li>
<li>You can also select the data center that is geographically closest to you or your users for better performance.</li>
<li>Click on "Review" and then "Create instance" to finalize the creation.</li>
</ol>
<h4 id="heading-step-5-access-your-database">Step 5: Access Your Database</h4>
<ol>
<li>Once the instance is created, click on it in the Dashboard.</li>
<li>Here, you'll see the "Details" tab which includes all the information you need to connect to your database: <code>URL</code>, <code>User &amp; Default database</code>, <code>Password</code>, and more.</li>
</ol>
<h3 id="heading-populate-the-db">Populate the DB</h3>
<h4 id="heading-step-1-login-to-elephantsql">Step 1: Login to ElephantSQL</h4>
<p>Open your web browser and navigate to the ElephantSQL website. Log<br>in to your account.</p>
<h4 id="heading-step-2-open-your-instance">Step 2: Open your Instance</h4>
<p>Once logged in, click on the name of the database instance you've set up.</p>
<h4 id="heading-step-3-navigate-to-the-sql-browser">Step 3: Navigate to the SQL Browser</h4>
<p>In the left sidebar, find and click on "SQL Browser" or something similar (it might say "Browser").</p>
<h4 id="heading-step-4-run-sql-query">Step 4: Run SQL Query</h4>
<p>In the SQL Query editor that appears, you can type or paste in your SQL command:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-string">"public"</span>.<span class="hljs-string">"Note"</span> (title, <span class="hljs-keyword">content</span>)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-string">'test title'</span>, <span class="hljs-string">'test content bla bla'</span>);
</code></pre>
<p>After entering the SQL, click on the "Execute" or "Run" button.</p>
<p>That should insert a new row into your <code>Note</code> table with the title 'test title' and content 'test content bla bla'.</p>
<h4 id="heading-optional-verify-the-insert">Optional: Verify the Insert</h4>
<p>You may also want to verify if the data has been inserted correctly. For that, you could use:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-string">"public"</span>.<span class="hljs-string">"Note"</span>;
</code></pre>
<p>Run this SQL query in the same SQL browser, and it should return all rows from the <code>Note</code> table, including the one you've just inserted.</p>
<p>And that's it! You've inserted a new row into your table through the ElephantSQL web console.</p>
<h3 id="heading-connect-to-db-from-nodejs-backend-using-prisma">Connect to DB from Node.js backend using Prisma</h3>
<h4 id="heading-step-1-copy-the-elephantsql-connection-url">Step 1: Copy the ElephantSQL Connection URL</h4>
<p>Once you've set up your ElephantSQL database, make sure to copy the connection URL that appears on your dashboard. This URL includes your username and password to the database, so keep it secure.</p>
<h4 id="heading-step-2-create-an-env-file">Step 2: Create an <code>.env</code> File</h4>
<p>Navigate to your <code>notes-app-server</code> directory and create a new <code>.env</code> file:</p>
<pre><code class="lang-bash">touch .env
</code></pre>
<p>Open this file and add the following line to specify the database connection URL:</p>
<pre><code class="lang-bash">DATABASE_URL=<span class="hljs-string">"your_connection_url_here"</span>
</code></pre>
<p>Make sure not to commit this <code>.env</code> file to your Git repository to keep your credentials secure.</p>
<h4 id="heading-step-3-initialize-prisma">Step 3: Initialize Prisma</h4>
<p>If you haven't installed Prisma yet, install it first:</p>
<pre><code class="lang-bash">npm install prisma --save-dev
</code></pre>
<p>Now, initialize Prisma in the <code>notes-app-server</code> directory:</p>
<pre><code class="lang-bash">npx prisma init
</code></pre>
<p>This command will create a new <code>prisma</code> folder containing a <code>schema.prisma</code> file.</p>
<h4 id="heading-step-4-configure-schemaprisma">Step 4: Configure <code>schema.prisma</code></h4>
<p>Open <code>schema.prisma</code> in your text editor. You'll see that Prisma has already generated some configurations for you. Update the <code>datasource</code> block to use the environment variable:</p>
<pre><code class="lang-javascript">datasource db {
  provider = <span class="hljs-string">"postgresql"</span>
  url      = env(<span class="hljs-string">"DATABASE_URL"</span>)
}
</code></pre>
<h4 id="heading-step-5-create-the-note-model">Step 5: Create the Note Model</h4>
<p>Below the <code>datasource</code> block, add a new <code>model</code> block to represent a <code>Note</code>:</p>
<pre><code class="lang-javascript">model Note {
  id      Int     @id @<span class="hljs-keyword">default</span>(autoincrement())
  title   <span class="hljs-built_in">String</span>
  content <span class="hljs-built_in">String</span>
}
</code></pre>
<h4 id="heading-step-6-generate-prisma-client-and-database-table">Step 6: Generate Prisma Client and Database Table</h4>
<p>Run the following command to generate your Prisma client and create the database tables:</p>
<pre><code class="lang-bash">npx prisma db push
</code></pre>
<h4 id="heading-step-7-add-prisma-to-your-application">Step 7: Add Prisma to Your Application</h4>
<p>First, import Prisma at the top of your <code>index.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;
</code></pre>
<p>Then, initialize the Prisma client:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
</code></pre>
<h4 id="heading-step-8-query-your-database">Step 8: Query Your Database</h4>
<p>Now you can use Prisma in your application to query the database. For example, in a <code>GET</code> endpoint:</p>
<pre><code class="lang-typescript">app.get(<span class="hljs-string">"/notes"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> notes = <span class="hljs-keyword">await</span> prisma.note.findMany();
  res.json(notes);
});
</code></pre>
<h3 id="heading-optional-install-thunder-client-in-vs-code">Optional: Install Thunder Client in VS Code</h3>
<p>(Feel free to skip this step if you already have a preferred API client)</p>
<p>Using <code>curl</code> is useful for quickly testing APIs, but it becomes cumbersome when you need to build out more complex requests. For instance, handling POST requests with custom bodies and headers can be more complicated. </p>
<p>To make API requests more straightforward, we'll install a client designed for this purpose.</p>
<p>While there are several options like Postman, we're going to focus on installing Thunder Client within VS Code, which makes it simple to execute requests right from your IDE.</p>
<p>To install Thunder Client, navigate to the Extensions section in VS Code and type "Thunder Client" in the search bar. You'll find it in the list of available extensions, identifiable by its purple logo. Click "Install," and upon completion, you'll see a Thunder Client option appear on the left-hand taskbar of your IDE.</p>
<p>Once you've clicked on Thunder Client, a list of your past requests will display. To initiate a new request, click the "New Request" button at the top. This action opens a new tab within Visual Studio Code.</p>
<p>Before proceeding, ensure that your server is running. Open the terminal and verify this. We will use Thunder Client to test our GET endpoint and get familiar with the request-making process. In the URL bar, enter the address of your 'notes' endpoint and specify that it's a GET request.</p>
<p>Click "Send," and you'll see a small window displaying the response. If the status code is 200 and you see an array containing your note, you've successfully made a GET request. Thunder Client will be our tool of choice for testing subsequent create, update, and delete requests. Of course, feel free to use any other tool you're comfortable with for this purpose.</p>
<h3 id="heading-create-post-endpoint">Create POST Endpoint</h3>
<p>In this section, we'll add an endpoint to our Express application that allows us to create a new note. Locate the <code>index.ts</code> file and insert the following code below your existing GET endpoint:</p>
<pre><code class="lang-typescript">app.post(<span class="hljs-string">"/api/notes"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { title, content } = req.body;

  <span class="hljs-keyword">if</span> (!title || !content) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">"title and content fields required"</span>);
  }

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> note = <span class="hljs-keyword">await</span> prisma.note.create({
      data: { title, content },
    });
    res.json(note);
  } <span class="hljs-keyword">catch</span> (error) {
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">"Oops, something went wrong"</span>);
  }
});
</code></pre>
<p>The structure is similar to the GET endpoint, but we're using <code>app.post</code> this time. We specify the URL for this POST endpoint and then define our function.</p>
<p>Inside the function, the first task is to extract <code>title</code> and <code>content</code> from the <code>req.body</code>. This is what the UI will send when a user submits the "Add Note" form.</p>
<p>After obtaining <code>title</code> and <code>content</code>, we utilize the Prisma client that we set up earlier to create a new note. We pass the <code>title</code> and <code>content</code> to the <code>prisma.note.create()</code> method, which returns a new note object complete with an ID. This object is then sent back as a JSON response.</p>
<p>To test the endpoint, go to the Thunder Client tab in VS Code. Switch the HTTP method from GET to POST while keeping the URL the same. Click the "Body" tab, which should default to JSON, and input some test values for <code>title</code> and <code>content</code>. After hitting "Send," you should receive a 200 OK status along with the created note, containing an ID, title, and content.</p>
<p>For robustness, we've added validation and error-handling. If either <code>title</code> or <code>content</code> is missing, the server returns a 400 Bad Request status with an appropriate error message. To test this, remove either <code>title</code> or <code>content</code> from the request body and resend it. You should now see a 400 status code along with your error message.</p>
<p>Additionally, we use a try-catch block to handle any errors thrown by the Prisma client. This helps in cases of database connection issues or other unforeseen errors, preventing the backend from crashing.</p>
<p>Finally, you can test the GET endpoint again. It should now return two notes: the first one manually added to the database, and the second one just created through Thunder Client. Switch the method back to GET in Thunder Client and hit "Send"; you should see two notes in the response.</p>
<h3 id="heading-create-put-endpoint">Create PUT Endpoint</h3>
<p>In this segment of the tutorial, we'll focus on adding the ability to update a note. Add the following code snippet below the code for your previous POST endpoint:</p>
<pre><code class="lang-javascript">app.put(<span class="hljs-string">"/api/notes/:id"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { title, content } = req.body;
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);

  <span class="hljs-keyword">if</span> (!title || !content) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">"title and content fields required"</span>);
  }

  <span class="hljs-keyword">if</span> (!id || <span class="hljs-built_in">isNaN</span>(id)) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">"ID must be a valid number"</span>);
  }

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> updatedNote = <span class="hljs-keyword">await</span> prisma.note.update({
      <span class="hljs-attr">where</span>: { id },
      <span class="hljs-attr">data</span>: { title, content },
    });
    res.json(updatedNote);
  } <span class="hljs-keyword">catch</span> (error) {
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">"Oops, something went wrong"</span>);
  }
});
</code></pre>
<p>The structure of this <code>app.put</code> function is similar to the GET and POST endpoints you've already created. The major difference is the <code>:id</code> parameter in the URL. This acts as a placeholder, allowing you to specify the ID of the note you wish to update.</p>
<p>Inside the function, you'll notice we extract <code>title</code> and <code>content</code> from <code>req.body</code>, just like before. Additionally, we retrieve the ID from <code>req.params</code> and convert it to an integer using <code>parseInt()</code>, as our database stores IDs as integers.</p>
<p>We've added validation checks to ensure that the <code>id</code> exists and is a valid number. If either <code>id</code>, <code>title</code>, or <code>content</code> is missing or invalid, the API returns a 400 status code along with an error message.</p>
<p>Next, we use a try-catch block to attempt the update operation. Within the <code>try</code> section, we call the <code>prisma.note.update()</code> function. We specify the <code>id</code> in a <code>where</code> object and provide the new <code>title</code> and <code>content</code> via a <code>data</code> object. If the operation succeeds, the updated note is sent back in the response. In case of an error, the <code>catch</code> block will return a 500 status and an error message.</p>
<p>To test this, switch to your Thunder Client tab in VS Code. Update the method to PUT and set the URL to include the ID of the note you want to update, for example, <code>/api/notes/3</code>. In the request body, send JSON data with the new <code>title</code> and <code>content</code>. Upon hitting "Send", a 200 status should confirm the update. The returned note should reflect your changes.</p>
<p>To double-check, perform a GET request on the <code>/api/notes</code> endpoint. You should see the updated note in the list.</p>
<p>Lastly, test the validation by supplying an invalid ID, like a random string. The API should return an error message stating that the ID must be a valid number.</p>
<h3 id="heading-create-delete-endpoint">Create DELETE Endpoint</h3>
<p>In addition to our existing endpoints, it's crucial to add validation for empty <code>title</code> or <code>content</code> fields in our <code>app.put</code> function, since these fields are required by our database. Revisit your <code>app.put</code> function in <code>index.ts</code> and add similar validation to what we added for the POST request. Specifically, if either <code>title</code> or <code>content</code> is empty, return a 400 status code along with an error message.</p>
<p>With that in place, let's move on to the DELETE endpoint. Add the following code just after your PUT endpoint:</p>
<pre><code class="lang-javascript">app.delete(<span class="hljs-string">"/api/notes/:id"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);

  <span class="hljs-keyword">if</span> (!id || <span class="hljs-built_in">isNaN</span>(id)) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">"ID field required"</span>);
  }

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> prisma.note.delete({
      <span class="hljs-attr">where</span>: { id },
    });
    res.status(<span class="hljs-number">204</span>).send();
  } <span class="hljs-keyword">catch</span> (error) {
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">"Oops, something went wrong"</span>);
  }
});
</code></pre>
<p>This <code>app.delete</code> function works similarly to the update (<code>app.put</code>) endpoint. It also accepts an ID as part of the URL parameters (<code>query params</code> should be <code>URL parameters</code> or <code>route parameters</code>).</p>
<p>First, we validate that the provided ID is a valid number. If it isn't, we return a 400 status code and an accompanying error message.</p>
<p>Once the ID is validated, we proceed to delete the note using Prisma's <code>delete</code> method. In the <code>try</code> block, we specify which note to delete by its ID in the <code>where</code> object. Upon successful deletion, we return a 204 status code, which indicates 'No Content.' This is a standard way to signal to the frontend or API consumers that the deletion was successful.</p>
<p>If an error occurs during the deletion, the <code>catch</code> block returns a 500 status code along with a generic error message.</p>
<p>To test the new DELETE endpoint, switch your HTTP method to <code>DELETE</code> in your testing tool (like Thunder Client or Postman). Use the ID of the note you wish to delete, such as <code>/api/notes/3</code>, and hit 'Send'. You should receive a 204 status code, indicating the operation was successful. To confirm, perform a GET request on your <code>/api/notes</code> endpoint and observe that the note with the specified ID has indeed been removed.</p>
<h2 id="heading-part-3-connect-ui-to-backend">PART 3 - Connect UI to Backend</h2>
<p>Now that we have our backend and UI ready, it's time to connect them. We will do this by using the built in <code>fetch</code> function to call our backend from our UI.</p>
<h3 id="heading-get-and-display-notes">Get and Display Notes</h3>
<p>Let's dive back into our frontend code. Just below our state declarations at the top of our component, we're going to introduce a <code>useEffect</code> hook:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// ...</span>
}, []);
</code></pre>
<p>Inside this <code>useEffect</code>, we'll define an asynchronous function named <code>fetchNotes</code>. We need to put this in a separate function because React does not support making the <code>useEffect</code> hook asynchronous directly:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchNotes = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>To handle any potential errors from the API, we'll wrap our API logic inside a <code>try-catch</code> block:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (e) {
  <span class="hljs-built_in">console</span>.log(e);
}
</code></pre>
<p>Inside the <code>try</code> block, we use the native <code>fetch</code> function to make an API call. Our API is running at <code>http://localhost:5000/api/notes</code>. By default, <code>fetch</code> performs a GET request, which is what we need:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/notes"</span>);
</code></pre>
<p>After making the request, we'll process the response and convert it to JSON. The API returns an array of notes, which we'll capture in a variable named <code>notes</code> of type <code>Note[]</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> notes: Note[] = <span class="hljs-keyword">await</span> response.json();
</code></pre>
<p>If everything goes smoothly, the next step is to update our state with the notes fetched from the API:</p>
<pre><code class="lang-jsx">setNotes(notes);
</code></pre>
<p>In the <code>catch</code> block, we'll log any errors that may occur:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">console</span>.log(e);
</code></pre>
<p>We've defined <code>fetchNotes</code>, but haven't called it yet. To invoke this function, add a call to <code>fetchNotes()</code> at the end of the <code>useEffect</code> block:</p>
<pre><code class="lang-jsx">fetchNotes();
</code></pre>
<p>Lastly, add an empty dependency array to ensure that this code only runs once when the component is first mounted:</p>
<pre><code class="lang-jsx">}, []);
</code></pre>
<p>After saving your changes, you should see the notes from your database displayed in the browser. If you've added or deleted notes directly through the database, those changes should be reflected here.</p>
<p>To wrap things up, you can remove any hardcoded array that you initially added to your <code>notes</code> state variable. Instead, populate it with the data fetched from the API:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [notes, setNotes] = useState&lt;Note[]&gt;([]);
</code></pre>
<p>This ensures that the <code>notes</code> state is initially empty, then populated by the <code>useEffect</code> through the <code>fetchNotes</code> function.</p>
<h3 id="heading-completed-code-for-this-section-2">Completed Code for this Section</h3>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> [notes, setNotes] = useState&lt;Note[]&gt;([]);


  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fetchNotes = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
          <span class="hljs-string">"http://localhost:5000/api/notes"</span>
        );

        <span class="hljs-keyword">const</span> notes: Note[] =
          <span class="hljs-keyword">await</span> response.json();

        setNotes(notes);
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-built_in">console</span>.log(e);
      }
    };

    fetchNotes();
  }, []);
</code></pre>
<h3 id="heading-save-new-note">Save New Note</h3>
<p>Next, let's explore how to save a note to our backend. We already have a function called <code>handleAddNote</code> that deals with adding a note to the UI:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAddNote = <span class="hljs-keyword">async</span> (
  event: React.FormEvent
) =&gt; {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>To start, remove any code that manually creates a new note object on the frontend. This is because our backend will return this object with all its properties once the note has been saved to the database.</p>
<p>As in our previous example, we'll use a <code>try-catch</code> block to handle the API logic and error handling:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// API logic here</span>
} <span class="hljs-keyword">catch</span> (e) {
  <span class="hljs-built_in">console</span>.log(e);
}
</code></pre>
<p>Place your existing state-changing function calls (<code>setNotes</code>, <code>setTitle</code>, and <code>setContent</code>) inside the <code>try</code> block. These will be executed after the API successfully saves the note:</p>
<pre><code class="lang-jsx">setNotes([newNote, ...notes]);
setTitle(<span class="hljs-string">""</span>);
setContent(<span class="hljs-string">""</span>);
</code></pre>
<p>To call the API, we'll use the <code>fetch</code> function, similar to how we fetched notes. The difference is that this time, we need to pass a second argument to <code>fetch</code> to specify the HTTP method and payload:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
  <span class="hljs-string">"http://localhost:5000/api/notes"</span>,
  {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
      title,
      content,
    }),
  }
);
</code></pre>
<p>Don't forget to add the <code>async</code> keyword to the <code>handleAddNote</code> function signature if you haven't already, as we are using the <code>await</code> keyword inside the function.</p>
<p>The server will respond with the newly created note object, which we can then add to our UI. Convert the response to JSON and store it in a variable named <code>newNote</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> newNote = <span class="hljs-keyword">await</span> response.json();
</code></pre>
<p>Finally, in the <code>catch</code> block, we log any errors that might occur:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">console</span>.log(e);
</code></pre>
<p>Also, make sure to add headers to specify the content type of the data we are sending:</p>
<pre><code class="lang-jsx">headers: {
  <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
}
</code></pre>
<p>Save your changes and test the functionality in the browser. Use the form to add a new note and click "Add Note." If everything is set up correctly, your new note should appear in the list.</p>
<h3 id="heading-completed-code-for-this-section-3">Completed Code for this Section</h3>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> handleAddNote = <span class="hljs-keyword">async</span> (
    event: React.FormEvent
  ) =&gt; {
    event.preventDefault();
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
        <span class="hljs-string">"http://localhost:5000/api/notes"</span>,
        {
          <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
          },
          <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
            title,
            content,
          }),
        }
      );

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

      setNotes([newNote, ...notes]);
      setTitle(<span class="hljs-string">""</span>);
      setContent(<span class="hljs-string">""</span>);
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-built_in">console</span>.log(e);
    }
  };
</code></pre>
<h3 id="heading-save-updated-note">Save Updated Note</h3>
<p>Next, let's explore how to save a note to our backend. We already have a function called <code>handleAddNote</code> that deals with adding a note to the UI:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAddNote = <span class="hljs-keyword">async</span> (
  event: React.FormEvent
) =&gt; {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>To start, remove any code that manually creates a new note object on the frontend. This is because our backend will return this object with all its properties once the note has been saved to the database.</p>
<p>As in our previous example, we'll use a <code>try-catch</code> block to handle the API logic and error handling:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// API logic here</span>
} <span class="hljs-keyword">catch</span> (e) {
  <span class="hljs-built_in">console</span>.log(e);
}
</code></pre>
<p>Place your existing state-changing function calls (<code>setNotes</code>, <code>setTitle</code>, and <code>setContent</code>) inside the <code>try</code> block. These will be executed after the API successfully saves the note:</p>
<pre><code class="lang-jsx">setNotes([newNote, ...notes]);
setTitle(<span class="hljs-string">""</span>);
setContent(<span class="hljs-string">""</span>);
</code></pre>
<p>To call the API, we'll use the <code>fetch</code> function, similar to how we fetched notes. The difference is that this time, we need to pass a second argument to <code>fetch</code> to specify the HTTP method and payload:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
  <span class="hljs-string">"http://localhost:5000/api/notes"</span>,
  {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
      title,
      content,
    }),
  }
);
</code></pre>
<p>Don't forget to add the <code>async</code> keyword to the <code>handleAddNote</code> function signature if you haven't already, as we are using the <code>await</code> keyword inside the function.</p>
<p>The server will respond with the newly created note object, which we can then add to our UI. Convert the response to JSON and store it in a variable named <code>newNote</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> newNote = <span class="hljs-keyword">await</span> response.json();
</code></pre>
<p>Finally, in the <code>catch</code> block, we log any errors that might occur:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">console</span>.log(e);
</code></pre>
<p>Also, make sure to add headers to specify the content type of the data we are sending:</p>
<pre><code class="lang-jsx">headers: {
  <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
}
</code></pre>
<p>Save your changes and test the functionality in the browser. Use the form to add a new note and click "Add Note." If everything is set up correctly, your new note should appear in the list.</p>
<h3 id="heading-completed-code-for-this-section-4">Completed Code for this Section</h3>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> handleAddNote = <span class="hljs-keyword">async</span> (
    event: React.FormEvent
  ) =&gt; {
    event.preventDefault();
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
        <span class="hljs-string">"http://localhost:5000/api/notes"</span>,
        {
          <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
          },
          <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
            title,
            content,
          }),
        }
      );

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

      setNotes([newNote, ...notes]);
      setTitle(<span class="hljs-string">""</span>);
      setContent(<span class="hljs-string">""</span>);
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-built_in">console</span>.log(e);
    }
  };
</code></pre>
<h3 id="heading-save-deleted-note">Save Deleted Note</h3>
<p>In this section, we'll discuss how to delete a note by invoking an API endpoint. We'll focus on the <code>deleteNote</code> function for this functionality:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> deleteNote = <span class="hljs-keyword">async</span> (
  event: React.MouseEvent,
  <span class="hljs-attr">noteId</span>: number
) =&gt; {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>First, we need to make our function asynchronous to handle API calls. So, add the <code>async</code> keyword to the function declaration like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> deleteNote = <span class="hljs-keyword">async</span> (
  event: React.MouseEvent,
  <span class="hljs-attr">noteId</span>: number
) =&gt; {
  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>Next, let's add a <code>try-catch</code> block to manage the API call. The <code>catch</code> block is essential for logging errors, which prevents the application from crashing unexpectedly:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// API logic here</span>
} <span class="hljs-keyword">catch</span> (e) {
  <span class="hljs-built_in">console</span>.log(e);
}
</code></pre>
<p>Copy the existing UI-update logic you have and paste it into the <code>try</code> block, right after the API call. This ensures that the UI only updates if the API call is successful.</p>
<p>Now, let's get to the main part—making the API call to delete the note. To do so, we'll use the <code>fetch</code> API:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">await</span> fetch(
  <span class="hljs-string">`http://localhost:5000/api/notes/<span class="hljs-subst">${noteId}</span>`</span>,
  {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"DELETE"</span>,
  }
);
</code></pre>
<p>Note that the URL is a template string. It allows us to inject the ID of the note (<code>noteId</code>) that we want to delete. This <code>noteId</code> is passed into our <code>deleteNote</code> function when the user clicks the delete button corresponding to a specific note.</p>
<p>We specify the HTTP method as "DELETE" to indicate that we're requesting to delete a note:</p>
<pre><code class="lang-jsx">method: <span class="hljs-string">"DELETE"</span>,
</code></pre>
<p>Unlike the 'add' or 'update' operations, there's no need to assign the API response to a variable, as we're not expecting any data to be returned:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">await</span> fetch(
  <span class="hljs-string">`http://localhost:5000/api/notes/<span class="hljs-subst">${noteId}</span>`</span>,
  {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"DELETE"</span>,
  }
);
</code></pre>
<p>After successfully deleting the note, we filter out the deleted note from our local notes state:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> updatedNotes = notes.filter(
  <span class="hljs-function">(<span class="hljs-params">note</span>) =&gt;</span> note.id !== noteId
);
setNotes(updatedNotes);
</code></pre>
<p>Finally, if everything goes smoothly and you save your changes, try running the application in the browser. Click the delete button for a specific note, and then refresh the page. You'll see that the note has been removed successfully.</p>
<h3 id="heading-completed-code-for-this-section-5">Completed Code for this Section</h3>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> deleteNote = <span class="hljs-keyword">async</span> (
    event: React.MouseEvent,
    <span class="hljs-attr">noteId</span>: number
  ) =&gt; {
    event.stopPropagation();

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> fetch(
        <span class="hljs-string">`http://localhost:5000/api/notes/<span class="hljs-subst">${noteId}</span>`</span>,
        {
          <span class="hljs-attr">method</span>: <span class="hljs-string">"DELETE"</span>,
        }
      );
      <span class="hljs-keyword">const</span> updatedNotes = notes.filter(
        <span class="hljs-function">(<span class="hljs-params">note</span>) =&gt;</span> note.id !== noteId
      );

      setNotes(updatedNotes);
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-built_in">console</span>.log(e);
    }
  };
</code></pre>
<h2 id="heading-the-end-why-not-try-the-bonus-challenges">The End - Why not try the bonus challenges?</h2>
<p>Congratulations on making it to the end! If you enjoyed this project, I have created <a target="_blank" href="https://www.codecoyotes.com/projects/react-node-notes-app">a list of additional challenges to try over at codecoyotes.com</a>. </p>
<p>If you have any questions or suggestions feel free to <a target="_blank" href="https://www.codecoyotes.com/contact">drop me a message here.</a> See you in the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Redux for Beginners – The Brain-Friendly Guide to Learning Redux ]]>
                </title>
                <description>
                    <![CDATA[ In this Redux for Beginners guide, we're going to: Learn about the different parts of Redux and how they work together Learn how to fetch data from an API using Redux Learn how to use Redux Toolkit to setup and work with Redux using less code And I... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/redux-for-beginners-the-brain-friendly-guide-to-redux/</link>
                <guid isPermaLink="false">66c8c903e9e57963a5d82aca</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Mon, 12 Apr 2021 14:09:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/04/react-redux-todo-app.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this Redux for Beginners guide, we're going to:</p>
<ul>
<li>Learn about the different parts of Redux and how they work together</li>
<li>Learn how to fetch data from an API using Redux</li>
<li>Learn how to use Redux Toolkit to setup and work with Redux using less code</li>
</ul>
<p>And I’ll give you some challenges which you can try at the end.</p>
<h2 id="heading-this-is-what-well-build">This is what we'll build</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-2021-04-08-at-08.49.52.png" alt="Image" width="600" height="400" loading="lazy">
<em>Yep, its a Todo List! But this one uses Redux which makes it a fancy todo list!</em></p>
<p>The user can:</p>
<ul>
<li>Add todos</li>
<li>Remove todos</li>
<li>Mark todos as complete</li>
<li>View the number of completed todos</li>
</ul>
<h3 id="heading-video-walkthrough">Video Walkthrough</h3>
<p>Heres a <a target="_blank" href="https://www.youtube.com/watch?v=fiesH6WU63I">video walkthrough</a> if you want to supplement your reading (on YouTube).</p>
<h3 id="heading-source-code">Source Code</h3>
<p>Finally, you can grab the <a target="_blank" href="https://github.com/chrisblakely01/react-redux-todo-app">finished code here</a> (on GitHub).</p>
<h2 id="heading-get-the-starter-code">Get the Starter Code</h2>
<p>I've provided some starter code that gives us a basic React UI with all the components in place. This lets us focus more on the Redux side of things which is the reason we're all here!</p>
<p>Let's start by opening a terminal and running the following commands:</p>
<pre><code>git clone https:<span class="hljs-comment">//github.com/chrisblakely01/react-redux-todo-app.git</span>
cd react-redux-todo-app/starter
npm install
npm start
</code></pre><p>This should fire up a browser with the app started. </p>
<p>Next, open the <code>react-redux-todo-app</code> folder up in your IDE (I'll be using VS Code). The project tree should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-2021-04-08-at-09.13.17.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You'll notice a few folders in here:</p>
<ul>
<li><strong>API</strong>: This is the API we'll use later in the project when we learn about working with API's in Redux (how exciting!) </li>
<li><strong>Final</strong>: This is the finished code. Note, if you run this, the API needs to be started as well. See the <strong>readme</strong> in the GitHub repo for how to do this</li>
<li><strong>Starter</strong>: This is the folder we'll be working in if you decide to follow along with the tutorial </li>
</ul>
<h2 id="heading-redux-overview">Redux Overview</h2>
<p>Before we get into the code, let's look at the different parts of Redux and how they work together.</p>
<p>Redux is made up of <strong>actions</strong>, <strong>reducers</strong>, <strong>state</strong> and the <strong>store.</strong> Each thing does one specific task. Lets take an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/ReduxDataFlowDiagram-49fa8c3968371d9ef6f2a1486bd40a26-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://redux.js.org/tutorials/essentials/part-1-overview-concepts">image from redux.js.org</a></em></p>
<p>Let's say we have a component that lets us deposit some money with the click of a button (the "UI" box in the diagram above).</p>
<p>When we click a button, we usually call a function which handles this event. This is where we would dispatch an action.</p>
<p><strong>Dispatch</strong> is a function given to us by Redux, and lets us <strong>trigger actions</strong>.</p>
<p>The <strong>action</strong> contains a <strong>type</strong>, and a <strong>payload</strong>. The type is typically just a string with the name of the action. The payload contains data we need to know about. For example, we can’t deposit any money without knowing the amount</p>
<p>The <strong>store</strong> receives the action, and is in charge of holding the state. Think of it like a database, in a sense that it holds all our data in one place</p>
<p>The store is also in charge of updating the state based on the action and the current state which it does by using <strong>reducers</strong>.</p>
<p>A <strong>reducer</strong> sounds fancy but its just a function that takes the current state from the store, and the action. It combines things together and returns the new state.</p>
<p>Think of it like a conveyor belt – it takes the old state and the action, does some work, and spits out the new state.</p>
<p>The store then saves this new state which is returned from the reducer and passes the state to the components. This causes them to re-render, displaying the new data.</p>
<h3 id="heading-why-do-we-need-all-this">Why do we need all this?</h3>
<p>Imagine an app with hundreds or even thousands of components. It would become unwieldy to pass state around and remember which component is changing the state, how it's changing the state, and so on.</p>
<p>By breaking things up like this, we give different responsibilities to different things, and we keep all our state in one place.</p>
<p>This makes it easier for us to understand and easier to test. For example, you can test reducers in isolation since they’re just pure functions. We can test that our actions dispatch correctly, and that our store correctly saves the state.</p>
<h2 id="heading-how-to-configure-our-store">How to Configure Our Store</h2>
<p>We’re going to use Redux toolkit to set up all the things we need to make Redux work, starting with the store.</p>
<p>Create a new folder in the <strong>src</strong> folder called <strong>redux.</strong> Within this folder create a file called <strong>store.js,</strong> and add the following code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> configureStore({
    <span class="hljs-attr">reducer</span>: {},
});
</code></pre>
<p>The configure store function does all the hard work for us. It creates the store which holds our state, combines our reducers, and has some nice built in middleware that we’ll use later.</p>
<p>The configureStore function gives us back a store, which we can export (line 3). This allows us to link the store to our app which we’ll do in a second.</p>
<p>We need to pass our reducers to the configureStore function, which we do by passing an object.</p>
<p>We haven’t created any reducers yet, but we could have as many reducers as we want here.</p>
<h3 id="heading-how-to-connect-the-store-to-the-app">How to Connect the Store to the App</h3>
<p>We have a store, and we have an app, so let's join these two things up!</p>
<p>Open up <strong>index.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">'./redux/store'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

ReactDOM.render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>We import the <strong>store</strong> and the <strong>Provider</strong> (at the top), and then we wrap our <strong>App</strong> component in the <strong>Provider</strong> component. The Provider needs to be given a store to use, so we pass in the store we just created. This gives our components access to the state that lives in the store.</p>
<h2 id="heading-how-to-create-a-slice">How to Create a Slice</h2>
<p>A <strong>slice</strong> gives us a way to store a piece, or slice, of data, and gives us all the things we need to change and retrieve that data. </p>
<p>You can think of it like a grouping of data, similar to database tables.</p>
<p>In the <strong>src/redux</strong> folder, create a new file called <strong>todoSlice.js</strong>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo1'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo2'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo3'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">true</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo4'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo5'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
    ],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },

    },
});


<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<p>The <strong>createSlice</strong> function will give us back some stuff and assign it to the todoSlice variable (line 3)</p>
<p>This is where we get our actions and reducers which we can export.</p>
<p>We need to pass some properties to this function so it gives us back the right things. We do this with an object.</p>
<p>First, we give the slice a name. We’re in the todo’s slice so we’ll call it todos. This is also what we’ll see in the Redux dev tools (line 4).</p>
<p>Next we add initial state. We’re going to add some dummy data for now. This can be empty, but we’re going to add stuff so we can see what’s going on (line 5)</p>
<p>Now we add the reducers. The reducer responds to the action, takes the current state, and creates new state based on the action payload. The first one we are adding is the <strong>addTodo</strong> reducer (line 13)</p>
<p>This is just a plain function. Redux passes in the <strong>state</strong> and <strong>action</strong> behind the scenes. The state is the current state of this slice, and the action contains the type and the payload.</p>
<p>So when we dispatch the <strong>addTodo</strong> action, this is the <strong>reducer</strong> that handles that action.</p>
<p>Within the reducer, this is where we want to perform the logic to update the state (line 14). </p>
<p>Since we’re adding a todo, the first thing we want to do is create a new todo object. This object is going to have the same properties that our other todos have. We’ll generate a new ID based on the date to make sure it's unique, take the title from the payload, and default completed to false.</p>
<p>Now we just push this to the state object. At this point, redux will take this new state and update the store</p>
<p>This is the first one we need, but we’ll add more reducers as we go through the tutorial</p>
<p>When we add a reducer object like this, the createSlice function creates actions based on the reducer names.</p>
<h3 id="heading-how-to-export-our-actions-and-reducer">How to export our actions and reducer</h3>
<p>We use destructuring to get the actions and export them, so our components can access them.</p>
<p>So the todoSlice has created a bunch of actions for us based on our reducer names, and we just use destructuring to get the addTodo action and export it (line 26).</p>
<p>And we export the reducer so we can add it to our store (line 28).</p>
<h2 id="heading-how-to-add-the-reducers-to-the-store">How to Add the Reducers to the Store</h2>
<p>Now we need to add our reducer to the store. In <strong>store.js</strong>, add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;
<span class="hljs-keyword">import</span> todoReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./todoSlice'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> configureStore({
    <span class="hljs-attr">reducer</span>: {
        <span class="hljs-attr">todos</span>: todoReducer,
    },
});
</code></pre>
<p>Remember that the store holds all our reducers and manages them for us.</p>
<p>For example we could have another reducer called userReducer in here and the store will handle everything for us. This just makes our code more manageable to maintain.</p>
<h2 id="heading-how-to-add-a-new-todo">How to Add a New Todo</h2>
<p>We’ve created the reducer and the action to add a todo. This doesn’t do anything yet because we haven’t dispatched the action.</p>
<h3 id="heading-dispatch-the-addtodo-action">Dispatch the addTodo action</h3>
<p>What we want to happen is when the user hits submit, we want to dispatch the addTodo action.</p>
<p>In <strong>AddTodoForm.js</strong>, when the user hits submit, we want to dispatch the addTodo action. </p>
<p>Update the code in <strong>AddTodoForm.js</strong> with the following:</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-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { addTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

<span class="hljs-keyword">const</span> AddTodoForm = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [value, setValue] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> dispatch = useDispatch();

    <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
        event.preventDefault();
        <span class="hljs-keyword">if</span> (value) {
            dispatch(
                addTodo({
                    <span class="hljs-attr">title</span>: value,
                })
            );
        }
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'form-inline mt-3 mb-3'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'sr-only'</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control mb-2 mr-sm-2'</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Add todo...'</span>
                <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>
                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setValue(event.target.value)}
            &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-primary mb-2'</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>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodoForm;
</code></pre>
<ul>
<li>We import the useDispatch hook and the addTodo action (line 2/line 3)</li>
<li>Now in our function that gets called when the form is submitted, we’ll add a call to dispatch the addTodo action (line 12)</li>
<li>For each todo we need to know the title, so we’ll add a new object and pass in the title. This object will get mapped to the action <strong>payload</strong> (line 13)</li>
</ul>
<p>Now if we try this, nothing happens in our UI because we haven’t updated the TodoList to pull data from Redux, which we’ll do in a second.</p>
<p>If we open the Redux dev tools, you can see under the action tabs that our action has been dispatched, and the payload has our title in it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-2021-04-09-at-07.18.47.png" alt="Image" width="600" height="400" loading="lazy">
<em>The action is being dispatched with the correct payload</em></p>
<p>You can also see that the state has updated with the new todo by clicking on the <strong>state</strong> tab.</p>
<h2 id="heading-how-to-display-the-todo-list">How to Display the Todo List</h2>
<p>Now that we’ve looked at dispatching actions and updating state, we’ll look at how to retrieve data from Redux</p>
<p>In our TodoList component we want to take the TODO’s from Redux, as opposed to using the dummy list</p>
<p>To do this we use what’s called the <strong>useSelector</strong> hook. Open up TodoList.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> TodoItem <span class="hljs-keyword">from</span> <span class="hljs-string">'./TodoItem'</span>;
<span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-keyword">const</span> TodoList = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todos = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group'</span>&gt;</span>
            {todos.map((todo) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">TodoItem</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{todo.id}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{todo.title}</span> <span class="hljs-attr">completed</span>=<span class="hljs-string">{todo.completed}</span> /&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoList;
</code></pre>
<p>The <strong>useSelector</strong> hook accepts a function, and returns us the data based on that function.</p>
<p>So we’ll pass in our function – in this case we’ll do an arrow function. This accepts the state which is passed in by Redux. In this case, we want to do state.todos to get all the todos.</p>
<p>Now this is going to go to the store, pick out all the todos from state, and assign this to the todos variable which we defined ourselves</p>
<p>Since we’ve done the hard work already to display the list in our JSX, we just need to replace the dummy list with whatever we received from Redux.</p>
<p>If we try this, you can see that the todos are now being pulled from our todosSlice!</p>
<p>The state value that gets passed in to the useSelector hook function is the entire state tree that is stored in Redux.</p>
<p>So if you have multiple slices of state, this will return the whole thing. This lets us do pretty cool things – for example if we wanted to get a specific todo, or filter the list, we can do this here in this function.</p>
<h2 id="heading-how-to-mark-a-todo-as-complete">How to Mark a Todo as Complete</h2>
<h3 id="heading-create-the-reduceraction">Create the reducer/action</h3>
<p>Next we’ll look at how to mark a todo as complete. This is interesting since it involves updating existing state. Update todoSlice.js with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo1'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo2'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo3'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">true</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo4'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo5'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
    ],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },
        <span class="hljs-attr">toggleComplete</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.id);
            state[index].completed = action.payload.completed;
        },
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, toggleComplete } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<p>We add our new reducer (line 21). Remember that each reducer accepts the current state and an action which gets passed in by Redux.</p>
<p>When our component dispatches the <strong>toggleComplete</strong> action, this reducer will handle that action.</p>
<p>Now that we have our reducer we need to implement the logic to update the state (line 22).</p>
<p>So remember that each todo in the list has an <strong>ID</strong>. Our component will pass this ID as part of the action payload and we’ll use the ID to determine which todo in the array we need to update.</p>
<p>We’ll use the ID to find the index of the todo in the array, so if the ID is 1, it will return index 0.</p>
<p>Now that we know the index, we can update the “completed” property for the given todo.</p>
<p>We’ll set the complete property for that todo to be whatever it is in the <strong>payload</strong>.</p>
<p>Lastly we export the action so that the components can dispatch it (line 30). Remember that the createSlice function automatically creates actions based on our reducer names, so since we have a toggleComplete reducer, that means we have a toggleComplete action.</p>
<h3 id="heading-dispatch-the-action">Dispatch the action</h3>
<p>Now when our checkbox is clicked, we want to trigger the toggleComplete action. Update <strong>TodoItem.js</strong> with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { toggleComplete } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

<span class="hljs-keyword">const</span> TodoItem = <span class="hljs-function">(<span class="hljs-params">{ id, title, completed }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> dispatch = useDispatch();

    <span class="hljs-keyword">const</span> handleCheckboxClick = <span class="hljs-function">() =&gt;</span> {
        dispatch(toggleComplete({ id, <span class="hljs-attr">completed</span>: !completed }));
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">list-group-item</span> ${<span class="hljs-attr">completed</span> &amp;&amp; '<span class="hljs-attr">list-group-item-success</span>'}`}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex justify-content-between'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex align-items-center'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'checkbox'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'mr-3'</span>
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleCheckboxClick}</span>
                        <span class="hljs-attr">checked</span>=<span class="hljs-string">{completed}</span>
                    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
                    {title}
                <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-danger'</span>&gt;</span>Delete<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">li</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoItem;
</code></pre>
<p>Now when our checkbox is clicked, we want to trigger the toggleComplete action.</p>
<p>In our TodoItem component we’ll create a click handle function that dispatches an action.</p>
<p>First we import toggleComplete/useDispatch (line 2/ line 3)</p>
<p>Next, we create a click handler function called handleCompleteClick (line 8). This will be an arrow function that dispatches our action. </p>
<p>We’ll call the dispatch function, and pass in the action we want to dispatch (line 9).</p>
<p>Remember, our reducer needs to know the ID of the todo item we’re changing, and what the new completed value is, so we’ll pass this in as our payload object. </p>
<p>We’ll pass in the ID and pass in a completed value, which will be the opposite of what the current completed value is. So if current value if true, the new value will be false, and vice versa.</p>
<p>Now we just call this function from our input (line 19).</p>
<h2 id="heading-how-to-delete-a-todo">How to Delete a Todo</h2>
<p>We’ll look at another example of using this pattern in our app with deleting a todo.</p>
<h3 id="heading-create-the-reducer">Create the reducer</h3>
<p>Jump into TodoSlice.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo1'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo2'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo3'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">true</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo4'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo5'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
    ],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },
        <span class="hljs-attr">toggleComplete</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.id);
            state[index].completed = action.payload.completed;
        },
        <span class="hljs-attr">deleteTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> state.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id !== action.payload.id);
        },
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, toggleComplete, deleteTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<p>We’ll create our reducer (line 25).</p>
<p>When our action is dispatched we’ll send the ID of the todo that was clicked, and then filter this TODO out of the current list in state.</p>
<p>Use the filter function to get all the todos that do not equal the ID in the payload (line 26). We have to return this since the filter function gives us a new array back.</p>
<p>Lastly, we’ll export our action which was created for us (line 31).</p>
<h3 id="heading-dispatch-the-action-1">Dispatch the action</h3>
<p>Now we need to dispatch our deleteTodo action when the delete button is clicked. Jump into <strong>TodoItem.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { toggleComplete, deleteTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

<span class="hljs-keyword">const</span> TodoItem = <span class="hljs-function">(<span class="hljs-params">{ id, title, completed }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> dispatch = useDispatch();

    <span class="hljs-keyword">const</span> handleCheckboxClick = <span class="hljs-function">() =&gt;</span> {
        dispatch(toggleComplete({ id, <span class="hljs-attr">completed</span>: !completed }));
    };

    <span class="hljs-keyword">const</span> handleDeleteClick = <span class="hljs-function">() =&gt;</span> {
        dispatch(deleteTodo({ id }));
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">list-group-item</span> ${<span class="hljs-attr">completed</span> &amp;&amp; '<span class="hljs-attr">list-group-item-success</span>'}`}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex justify-content-between'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex align-items-center'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'checkbox'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'mr-3'</span>
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleCheckboxClick}</span>
                        <span class="hljs-attr">checked</span>=<span class="hljs-string">{completed}</span>
                    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
                    {title}
                <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDeleteClick}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-danger'</span>&gt;</span>
                    Delete
                <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">li</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoItem;
</code></pre>
<p>We'll create the handleDeleteClick function (line 12) which will dispatch the delete action, passing the ID as an object in the payload. Remember, the reducer needs to know the ID of the todo to be removed.</p>
<h2 id="heading-how-to-display-total-completed-items">How to Display Total Completed Items</h2>
<p>Next we’ll look at displaying the number of completed items. Open up <strong>TotalCompleteItems.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

<span class="hljs-keyword">const</span> TotalCompleteItems = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todos = useSelector(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span>
        state.todos.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.completed === <span class="hljs-literal">true</span>)
    );

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Total complete items: {todos.length}<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TotalCompleteItems;
</code></pre>
<p>First we import the useSelector hook (line 2) and assign this to a variable so we can use it (line 5).</p>
<p>Now we can pass a function to tell Redux what we want to return. We’ll use the filter function to return all the todos that have a completed value of true (line 6).</p>
<p>Remember that the state value that gets passed to the selector is the TOTAL state tree, which is why we need to specify the todos in here.</p>
<p>Now the result of our function gets passed to the todos variable. Since we used the filter function, the result is an array.</p>
<p>Now we can use this variable however we want, so we’ll output the length in our JSX (line 9).</p>
<p>So whenever this component mounts, it's going to go and get the todos that are completed, and output he length in the JSX. </p>
<p>Now if you save and run the code, you'll see every time we tick a todo, the count at the bottom gets updated!</p>
<h2 id="heading-how-to-work-with-an-api-in-redux">How to Work with an API in Redux</h2>
<p>To do API calls in Redux, we need what is called middleware.</p>
<p>Instead of dispatching an action that goes straight to the reducer, we dispatch an action that calls a thunk, which does the API call.</p>
<p>This then creates a normal action, and sends it on its way to the reducer. Let's have a look at a diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/ReduxAsyncDataFlowDiagram-d97ff38a0f4da0f327163170ccc13e80.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Image from redux.js.org</em></p>
<p>Instead of dispatching a plain action, our component dispatches an action that calls a <strong>thunk.</strong></p>
<p>This action gets intercepted by the middleware, which does the API call.</p>
<p>Once the API does its thing and we get the response back, the middleware takes the data and dispatches a plain old action.</p>
<p>So the payload here could be whatever was returned from the API.</p>
<p>From here things go on as we’re used to – a reducer handles the action, accepting the current state and the action, and returns some new state.</p>
<p>The flow is the same as what we’ve learned so far – we’re just adding an extra step in between which handles the API call.</p>
<p>This is the logical place to do this, as we can’t do the API call in our components since it would be difficult to reuse the code, and we can’t do the API call in the reducer because the reducer is a pure function that creates new state only.</p>
<h3 id="heading-setup-the-api">Setup the API</h3>
<p>Now we’re going to connect our app to an API, so we can practice working with APIs in Redux.</p>
<p>I’ve included a prebuilt API that we’ll use for this.</p>
<p>If you haven't cloned the source code already, you do so by opening a terminal and typing:</p>
<pre><code>Git clone https:<span class="hljs-comment">//github.com/chrisblakely01/react-redux-todo-app.git</span>
</code></pre><p>Once you have the code cloned, run the following:</p>
<pre><code>cd react-redux-todo-app/api
npm install
npm run server
</code></pre><p>Test it by going to <strong>localhost:7000/todos</strong> in the browser, and you should see an array of todos returned:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-2021-04-09-at-08.08.31.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Note if you stop/start the server, any data you changed will be lost since its not connected to a database!</p>
<h2 id="heading-how-to-get-todos-from-the-api">How to Get Todos from the API</h2>
<p>Let's start by getting the todos from the API. Jump into <strong>todoSlice.js</strong> and update it with the following:</p>
<pre><code><span class="hljs-keyword">import</span> { createAsyncThunk, createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getTodosAsync = createAsyncThunk(
    <span class="hljs-string">'todos/getTodosAsync'</span>,
    <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'http://localhost:7000/todos'</span>);
        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todos = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todos };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo1'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo2'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo3'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">true</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo4'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'todo5'</span>, <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span> },
    ],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },
        <span class="hljs-attr">toggleComplete</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.id);
            state[index].completed = action.payload.completed;
        },
        <span class="hljs-attr">deleteTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> state.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id !== action.payload.id);
        },
    },
        <span class="hljs-attr">extraReducers</span>: {
        [getTodosAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> action.payload.todos;
        },
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, toggleComplete, deleteTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre><h3 id="heading-create-the-api-callthunk">Create the API call/Thunk</h3>
<p>The first thing we’ll do is import the createAsyncThunk function and create our thunk (line 3). A thunk is a function that returns another function.</p>
<p>This thunk is the new action which we dispatch from our components.</p>
<p>This will in turn dispatch its own action when the response completes, with the data from the response as the payload.</p>
<p>We need to pass some stuff to the createAsyncThunk function, so we'll give it a name, and pass in a function that uses the fetch API to get the data (line 4 / line 5).</p>
<p>If the response is good, we will convert the response to JSON. The response comes back as a string so we need to convert it to an object (line 8).</p>
<p>Lastly we’ll return an object containing our todos. Remember that the API returns an array of todos.</p>
<p>Once the function returns, it will dispatch an action. Whatever we return, in this case an object containing the todo array, will be the payload of the action (line 9). All this is done behind the scenes.</p>
<h3 id="heading-create-the-reducer-1">Create the Reducer</h3>
<p>Now we need to implement the reducer logic which handles this action.</p>
<p>We do this within the extraReducers object (line 39 in the code snippet above). This is where we specify additional reducers that our todoSlice can use.</p>
<p>The syntax is a bit different, as our thunk will dispatch a number of actions.</p>
<p>The action we care about right now is the fulfilled action. When the thunk dispatches this action, this means the API call in our thunk has completed.</p>
<p>These reducers work the same as our plain reducers – they are just a function that accepts the current state and the payload.</p>
<p>Now we’ll return the todos that came in the payload, at which point Redux will update the state for us.</p>
<p>We now have our new action, and our reducer, we just need to export our thunk (line 3).</p>
<h3 id="heading-dispatch-the-action-2">Dispatch the Action</h3>
<p>Now we have to trigger the action that fetches the todo. The best place to do this is when the TodoList component gets loaded for the first time.</p>
<p>Open up TodoList.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> TodoItem <span class="hljs-keyword">from</span> <span class="hljs-string">'./TodoItem'</span>;
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { getTodosAsync } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

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

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

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group'</span>&gt;</span>
            {todos.map((todo) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">TodoItem</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{todo.id}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{todo.title}</span> <span class="hljs-attr">completed</span>=<span class="hljs-string">{todo.completed}</span> /&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoList;
</code></pre>
<p>First we'll import the useDispatch hook, and assign this to a variable (line 7). </p>
<p>Next we import the action we want to dispatch (line 4).</p>
<p>We want to get the Todos as soon as the component loads, so we’ll add the <strong>useEffect hook</strong> (line 10).</p>
<p>From here, we dispatch our action (line 11).</p>
<p>When the state in the store updates, the useSelector hook gets notified and updates the todos variable with the new todos taken from state.</p>
<p>Try this out and see it in action!</p>
<h2 id="heading-how-to-add-a-todo-via-api">How to Add a Todo via API</h2>
<p>Next we'll look at how to create a Todo and persist it on the API. This will be similar to what we had before, so open up <strong>TodoSlice.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createAsyncThunk, createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getTodosAsync = createAsyncThunk(
    <span class="hljs-string">'todos/getTodosAsync'</span>,
    <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'http://localhost:7000/todos'</span>);
        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todos = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todos };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addTodoAsync = createAsyncThunk(
    <span class="hljs-string">'todos/addTodoAsync'</span>,
    <span class="hljs-keyword">async</span> (payload) =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'http://localhost:7000/todos'</span>, {
            <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
            <span class="hljs-attr">headers</span>: {
                <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
            },
            <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">title</span>: payload.title }),
        });

        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todo = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todo };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },
        <span class="hljs-attr">toggleComplete</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.id);
            state[index].completed = action.payload.completed;
        },
        <span class="hljs-attr">deleteTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> state.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id !== action.payload.id);
        },
    },
    <span class="hljs-attr">extraReducers</span>: {
        [getTodosAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> action.payload.todos;
        },
        [addTodoAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            state.push(action.payload.todo);
        },
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, toggleComplete, deleteTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<h3 id="heading-create-the-api-callthunk-1">Create the API call/Thunk</h3>
<p>We're creating another thunk, giving it a name, and creating our async function. This time we pass the payload parameter, as we need to know the title of the Todo. This payload contains whatever was sent to us by the component when it dispatched the action.</p>
<p>Use the fetch API, this time we need to pass an object with some configuration to indicate that the fetch request is a POST. We'll pass in the content-type and stringify the body (line 17).</p>
<p>Now if the response is OK, the API will give us back a Todo object with a title, ID, and completed value.</p>
<p>Similar to before if the response is ok we’ll return the data, which in this case is a single todo object. </p>
<h3 id="heading-create-the-reducer-2">Create the Reducer</h3>
<p>Similar to before, add a fulfilled function, update the state by pushing this todo to the todos array (line 56).</p>
<h3 id="heading-dispatch-the-action-3">Dispatch the Action</h3>
<p>Now open up <strong>AddTodoForm.js</strong> and add the following:</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-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { addTodoAsync } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

<span class="hljs-keyword">const</span> AddTodoForm = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [value, setValue] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> dispatch = useDispatch();

    <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
        event.preventDefault();
        <span class="hljs-keyword">if</span> (value) {
            dispatch(
                addTodoAsync({
                    <span class="hljs-attr">title</span>: value,
                })
            );
        }
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'form-inline mt-3 mb-3'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'sr-only'</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control mb-2 mr-sm-2'</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Add todo...'</span>
                <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>
                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setValue(event.target.value)}
            &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-primary mb-2'</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>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodoForm;
</code></pre>
<p>Note that all we're really doing here is changing our onSubmit function to dispatch the <strong>addTodoAsync</strong> action rather than the <strong>addTodo</strong> action (line 13).</p>
<p>Now if you try this in the browser by adding a todo, you'll notice the todo persists – even after you refresh the page!</p>
<h2 id="heading-how-to-mark-a-todo-as-complete-via-api">How to Mark a Todo as Complete via API</h2>
<p>So I’m hoping you’re starting to see how this all works, but we’ll go through one last example just to make sure.</p>
<p>We need to call the API to update the “completed” property when the user clicks the checkbox.</p>
<p>Jump into <strong>TodoSlice.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { createAsyncThunk, createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getTodosAsync = createAsyncThunk(
    <span class="hljs-string">'todos/getTodosAsync'</span>,
    <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'http://localhost:7000/todos'</span>);
        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todos = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todos };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addTodoAsync = createAsyncThunk(
    <span class="hljs-string">'todos/addTodoAsync'</span>,
    <span class="hljs-keyword">async</span> (payload) =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'http://localhost:7000/todos'</span>, {
            <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
            <span class="hljs-attr">headers</span>: {
                <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
            },
            <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">title</span>: payload.title }),
        });

        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todo = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todo };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> toggleCompleteAsync = createAsyncThunk(
    <span class="hljs-string">'todos/completeTodoAsync'</span>,
    <span class="hljs-keyword">async</span> (payload) =&gt; {
        <span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:7000/todos/<span class="hljs-subst">${payload.id}</span>`</span>, {
            <span class="hljs-attr">method</span>: <span class="hljs-string">'PATCH'</span>,
            <span class="hljs-attr">headers</span>: {
                <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
            },
            <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">completed</span>: payload.completed }),
        });

        <span class="hljs-keyword">if</span> (resp.ok) {
            <span class="hljs-keyword">const</span> todo = <span class="hljs-keyword">await</span> resp.json();
            <span class="hljs-keyword">return</span> { todo };
        }
    }
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> todoSlice = createSlice({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'todos'</span>,
    <span class="hljs-attr">initialState</span>: [],
    <span class="hljs-attr">reducers</span>: {
        <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> todo = {
                <span class="hljs-attr">id</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
                <span class="hljs-attr">title</span>: action.payload.title,
                <span class="hljs-attr">completed</span>: <span class="hljs-literal">false</span>,
            };
            state.push(todo);
        },
        <span class="hljs-attr">toggleComplete</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.id);
            state[index].completed = action.payload.completed;
        },
        <span class="hljs-attr">deleteTodo</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> state.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id !== action.payload.id);
        },
    },
    <span class="hljs-attr">extraReducers</span>: {
        [getTodosAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> action.payload.todos;
        },
        [addTodoAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            state.push(action.payload.todo);
        },
        [toggleCompleteAsync.fulfilled]: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> index = state.findIndex(
                <span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.id === action.payload.todo.id
            );
            state[index].completed = action.payload.todo.completed;
        },
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addTodo, toggleComplete, deleteTodo } = todoSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoSlice.reducer;
</code></pre>
<h3 id="heading-create-the-api-callthunk-2">Create the API call/Thunk</h3>
<p>We're creating our Async thunk as usual (line 32).</p>
<p>This time its going to be a PATCH, as we’re updating part of an object. We’ll pass the ID via the URL, and we’ll pass the completed value taken from the payload.</p>
<p>The response will give us back the updated Todo object, so we’ll return that which will get passed to the reducer as part of the action.</p>
<h3 id="heading-create-the-reducer-3">Create the Reducer</h3>
<p>Now we'll handle the <strong>toggleCompleteAsync.fulfilled</strong> action. </p>
<p>We use the ID from the payload to get the index, and update the todo at that position with whatever the new completed value is (line 77).</p>
<h3 id="heading-dispatch-the-action-4">Dispatch the Action</h3>
<p>Finally, we just need to dispatch our new action. Jump into TodoItem.js and update it with the following:</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> { toggleCompleteAsync, deleteTodo } <span class="hljs-keyword">from</span> <span class="hljs-string">'../redux/todoSlice'</span>;

<span class="hljs-keyword">const</span> TodoItem = <span class="hljs-function">(<span class="hljs-params">{ id, title, completed }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> dispatch = useDispatch();

    <span class="hljs-keyword">const</span> handleCheckboxClick = <span class="hljs-function">() =&gt;</span> {
        dispatch(toggleCompleteAsync({ id, <span class="hljs-attr">completed</span>: !completed }));
    };

    <span class="hljs-keyword">const</span> handleDeleteClick = <span class="hljs-function">() =&gt;</span> {
        dispatch(deleteTodo({ id }));
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">list-group-item</span> ${<span class="hljs-attr">completed</span> &amp;&amp; '<span class="hljs-attr">list-group-item-success</span>'}`}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex justify-content-between'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'d-flex align-items-center'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'checkbox'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'mr-3'</span>
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleCheckboxClick}</span>
                        <span class="hljs-attr">checked</span>=<span class="hljs-string">{completed}</span>
                    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
                    {title}
                <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDeleteClick}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-danger'</span>&gt;</span>
                    Delete
                <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">li</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoItem;
</code></pre><p>Again, all we're doing here is dispatching the <strong>toggleCompleteAsync</strong> action from our event handler function (line 8).</p>
<p>Now, if you open this in the browser and toggle a few todos as complete, you'll notice the state is saved even after you refresh the page.</p>
<h2 id="heading-challenge-how-to-delete-a-todo-via-api">Challenge - How to Delete a Todo via API</h2>
<p>One to practice yourself is to delete the todo via the API! The API I've provided has support to delete todos by passing an ID. Some tips to get started.</p>
<p>First, you'll need to create an async thunk/API call similar to what we did before. The request to delete a Todo will look like this:</p>
<pre><code><span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:7000/todos/<span class="hljs-subst">${payload.id}</span>`</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">'DELETE'</span>,
});
</code></pre><p>Next, you will need to add a <strong>reducer</strong> that updates the state when the response completes</p>
<p>And you will need to <strong>dispatch an action</strong> when the button is clicked which triggers the thunk you created at step 1.</p>
<p>You can find the solution in the <strong>final</strong> code on GitHub!</p>
<h2 id="heading-thanks-for-reading">Thanks for Reading!</h2>
<p><a href="https://www.reactheroes.com">
<img src="https://i.ibb.co/rs79F7Z/Screenshot-2021-04-12-at-10-44-16.png" alt="Screenshot-2021-04-12-at-10-44-16" width="1150" height="510" loading="lazy">
</a></p>
<h2 id="heading-ia"> </h2>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build a React Budget Tracker App – Learn React & Context API with this Fun Project ]]>
                </title>
                <description>
                    <![CDATA[ In this React Budget Tracker App tutorial we're going to: We’ll learn how break down a UI into React components Learn how to work with state using the Context API Learn about actions, reducers, and the dispatch function  And I’ll give you some chal... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-budget-tracker-app/</link>
                <guid isPermaLink="false">66c8c8fd85ffc69fd028a826</guid>
                
                    <category>
                        <![CDATA[ app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React context ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Fri, 12 Mar 2021 19:24:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/03/react-budget-app-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this React Budget Tracker App tutorial we're going to:</p>
<ul>
<li>We’ll learn how break down a UI into React components</li>
<li>Learn how to work with state using the Context API</li>
<li>Learn about actions, reducers, and the dispatch function </li>
</ul>
<p>And I’ll give you some challenges which you can try at the end!</p>
<h2 id="heading-this-is-what-well-build">This is what we'll build:</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-09.20.33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The user can:</p>
<ul>
<li>Add expenses which have a name and a cost</li>
<li>Remove expenses</li>
<li>View how much of their budget is remaining</li>
<li>View how much they've spent so far </li>
<li>(Challenge) Edit budget </li>
<li>(Challenge) Search expenses</li>
</ul>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<p><a target="_blank" href="https://youtu.be/aeYxBd1it7I">Heres a video walkthrough if you want to supplement your reading (on YouTube)</a></p>
<h2 id="heading-source-code">Source Code</h2>
<p>Finally, in case you get lost while following along, <a target="_blank" href="https://github.com/chrisblakely01/react-budget-app">you can grab the finished code here (on GitHub)</a>.</p>
<p>Let's Go!</p>
<h2 id="heading-how-to-setup-a-react-project">How to Setup a React Project</h2>
<p>The first thing we need to do is setup a React project. For this we'll use <code>create-react-app</code>. </p>
<p>Fire up a terminal and type:</p>
<p><code>npx create-react-app budget-tracker</code> </p>
<p>When that's finished doing its thing we're going to install Bootstrap. This will give us ready-made styles we can use instead of having to create our own in CSS. </p>
<p>In the same terminal, change to your working directory, and install Bootstrap:</p>
<pre><code>cd budget-tracker
npm i bootstrap
</code></pre><p>Next we're going to install a package that allows us to generate IDs. We'll be using IDs to identify each expense in the list, so this is important.</p>
<p>Run the following command in your project directory:</p>
<pre><code>npm i uuid
</code></pre><p>The last package we need to install gives us some icons to use, which saves us from having to create them ourselves.</p>
<p>Run the following command in your project directory:</p>
<pre><code>npm i react-icons
</code></pre><p>Now open up the project in VS Code (or whatever IDE you use). You should see some stuff appear in the project tree (this is our empty React project). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-09.37.55-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can ignore most of this, as we'll be creating our own components. Open up App.js, delete everything, and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>What this does:</p>
<ul>
<li>Imports the bootstrap CSS into our project</li>
<li>Creates a component that displays "Hello React!" with paragraph tags</li>
<li>Exports this component so other components can use it</li>
</ul>
<p>Next we'll fire up the app and make sure everything is working as it should. Open a terminal (either in VS Code or otherwise) and start the app by typing the following:</p>
<pre><code>npm start
</code></pre><p>All being well, the app should start and open in a browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-09.45.18.png" alt="Image" width="600" height="400" loading="lazy">
<em>The text "Hello React" should appear on the page. This means your app is working!</em></p>
<p>Success! Now we're ready to start building out our React components.</p>
<h2 id="heading-how-to-put-the-ui-components-in-place">How to Put the UI Components in Place</h2>
<p>One approach to building apps is to start by putting the UI components in place with some dummy data. This usually helps with visualising what state objects are needed, and usually means less rework later on. </p>
<p>With that in mind we're going to put our UI components in place starting at the top and working down. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-10.04.55.png" alt="Image" width="600" height="400" loading="lazy">
<em>We'll add a title, then add a new component for each of the "boxes" shown. We'll add some dummy data just to get things displaying correctly</em></p>
<h3 id="heading-how-to-create-the-budget-component">How to Create the Budget Component</h3>
<p>Jump into the code, in the <strong>src</strong> folder, create a new folder called <strong>components.</strong> Within this, create a file called <strong>Budget.js.</strong> Your project structure should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-10.13.37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Open up <strong>Budget.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Budget = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'alert alert-secondary'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Budget: £2000<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Budget;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating a new component called <strong>Budget</strong> (line 3)</li>
<li>Using the <strong>Bootstrap Alert</strong> classes to gives us a nice gray background (line 5)</li>
<li>Adding some text and hard coding a value (line 6)</li>
</ul>
<h3 id="heading-how-to-create-the-remaining-component">How to Create the <code>Remaining</code> Component</h3>
<p>Next we'll create the <strong><code>Remaining</code></strong> component, which shows how much budget the user has left.</p>
<p>Create a new file under <strong>src/components</strong> called <strong>Remaining.js</strong>. Open it up and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Remaining = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'alert alert-success'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Remaining: £1000<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Remaining;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating a new component called <strong>Remaining</strong> (line 3)</li>
<li>Using the <strong>Bootstrap Alert</strong> classes to gives us a green background (line 5)</li>
<li>Adding some text and hard coding a value (line 6)</li>
<li>Adding Spent so Far</li>
</ul>
<p>Lastly, we'll create the <strong>Spent so Far</strong> component, which shows how much the user has spent so far.</p>
<p>Create a new file under <strong>src/components</strong> called <strong>ExpenseTotal.js</strong>. Open it up and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> ExpenseTotal = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'alert alert-primary'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Spent so far: £1000<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseTotal;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating a new component called <strong>ExpenseTotal</strong> (line 3)</li>
<li>Using the <strong>Bootstrap Alert</strong> classes to gives us a blue background (line 5)</li>
<li>Adding some text and hard coding a value (line 6)</li>
</ul>
<h3 id="heading-how-to-add-a-title-and-render-our-components">How to Add a Title and Render our Components</h3>
<p>At this point you might be thinking, "these components all look the same, what gives?!". This is true, although remember we're just adding some hard coded data for now. Later, each component will do different things to display the data dynamically.</p>
<p>Now we've created our components, we need to render them in <strong>App.js.</strong> Open App.js and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> Budget <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Budget'</span>;
<span class="hljs-keyword">import</span> Remaining <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Remaining'</span>;
<span class="hljs-keyword">import</span> ExpenseTotal <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseTotal'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">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">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>My Budget Planner<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">Budget</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">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">Remaining</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">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseTotal</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Importing our different components (lines 3-5)</li>
<li>Adding a bootstrap container that helps us center our App on the page (line 9)</li>
<li>Adding a title (line 9)</li>
<li>Adding a Bootstrap row (line 10)</li>
<li>Adding a column within the row for each of our components so far (lines 12-20)</li>
</ul>
<p>Now if you run the app, you should see the title, and our components rendered on the page!</p>
<h3 id="heading-how-to-create-the-expense-list-component">How to Create the Expense List Component</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-07-at-10.31.44.png" alt="Image" width="600" height="400" loading="lazy">
<em>The expenses list shows the expenses the user has added so far, displaying the Name, cost, and a delete button for each</em></p>
<p>Next we'll build the <strong>ExpenseList</strong> component. This component will be in charge of taking a list of expenses, and rendering an <strong>ExpenseItem</strong> component for each item. </p>
<p>We'll add some dummy data, to make sure our UI looks good and things are working as intended. Later, this stuff will come from context.</p>
<p>Start by creating a new file under <strong>src/components</strong> called <strong>ExpenseList.js</strong>. Open up ExpenseList.js and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> ExpenseItem <span class="hljs-keyword">from</span> <span class="hljs-string">'./ExpenseItem'</span>;

<span class="hljs-keyword">const</span> ExpenseList = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> expenses = [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">12</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'shopping'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">40</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">13</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'holiday'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">400</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">14</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'car service'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">50</span> },
    ];

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group'</span>&gt;</span>
            {expenses.map((expense) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseItem</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{expense.id}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{expense.name}</span> <span class="hljs-attr">cost</span>=<span class="hljs-string">{expense.cost}</span> /&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseList
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Adding a dummy list of expenses. For each expense we need an ID, a name, and a cost. Later, we'll take this list from context (line 4)</li>
<li>Creating a list (line 11)</li>
<li>Using the map function to iterate over the expenses and displaying an ExpenseItem component (we haven't created this yet! Line 12)</li>
<li>Passing the ID, name, and cost to the ExpenseItem component as props</li>
</ul>
<h3 id="heading-how-to-create-the-expense-item-component">How to Create the Expense Item Component</h3>
<p>Now we've created a component to hold our list, we need a component to render each item. Create a new file in the <strong>src/components</strong> folder called <strong>ExpenseItem.js.</strong> Open it up and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { TiDelete } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-icons/ti'</span>;

<span class="hljs-keyword">const</span> ExpenseItem = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group-item d-flex justify-content-between align-items-center'</span>&gt;</span>
            {props.name}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'badge badge-primary badge-pill mr-3'</span>&gt;</span>
                    £{props.cost}
                <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">TiDelete</span> <span class="hljs-attr">size</span>=<span class="hljs-string">'1.5em'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">TiDelete</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">li</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseItem;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating a list item (line 6)</li>
<li>Rendering the name of the expense, which we get from props (line 7)</li>
<li>Rendering the cost of the expense, which we also get from props</li>
<li>We're displaying a DeleteIcon (line 12) which we get from react-icons package (line 2)</li>
</ul>
<h3 id="heading-how-to-render-the-expenselist-component">How to Render the ExpenseList Component</h3>
<p>Now we've created our components, we just have to render ExpenseList in App.js. Open up App.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> Budget <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Budget'</span>;
<span class="hljs-keyword">import</span> Remaining <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Remaining'</span>;
<span class="hljs-keyword">import</span> ExpenseTotal <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseTotal'</span>;
<span class="hljs-keyword">import</span> ExpenseList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseList'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">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">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>My Budget Planner<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Budget</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Remaining</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseTotal</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Expenses<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseList</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>What's new:</p>
<ul>
<li>We imported our ExpenseList (line 6)</li>
<li>Added a new Bootstrap row (line 24)</li>
<li>Rendered our ExpenseList (line 26)</li>
</ul>
<p>Now if you save/run the App, you'll see the Expenses list has appeared!</p>
<h3 id="heading-how-to-create-the-add-expense-form-component">How to create the "Add Expense" form component</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-08-at-07.28.29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Our UI components are nearly complete! The last component we need is the "Add Expense" form component, which lets users add new expenses. We'll put the UI components for the form in place first, then come back later and add the fancy stuff.</p>
<p>Create a new file in <strong>src/components</strong> called <strong>AddExpenseForm.js</strong>. Fire this up and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'name'</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'name'</span>
                    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'cost'</span>&gt;</span>Cost<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'cost'</span>
                    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</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> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-primary mt-3'</span>&gt;</span>
                        Save
                    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddExpenseForm;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Adding our form tags (line 6)</li>
<li>Adding a label/input for our <strong>name</strong> field (line 9)</li>
<li>Adding a label/input for our <strong>cost</strong> field (line 18)</li>
<li>Adding a button to submit the form (line 30)</li>
</ul>
<h3 id="heading-how-to-render-the-addexpenseform-component">How to Render the AddExpenseForm component</h3>
<p>Finally in App.js, we have to render our new component. Update App.js with the following:</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> Budget <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Budget'</span>;
<span class="hljs-keyword">import</span> Remaining <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Remaining'</span>;
<span class="hljs-keyword">import</span> ExpenseTotal <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseTotal'</span>;
<span class="hljs-keyword">import</span> ExpenseList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseList'</span>;
<span class="hljs-keyword">import</span> AddExpenseForm <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddExpenseForm'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">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">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>My Budget Planner<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Budget</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Remaining</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseTotal</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Expenses<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseList</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Add Expense<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">AddExpenseForm</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>What's changed:</p>
<ul>
<li>Imported the AddExpenseForm (line 7)</li>
<li>Rendered the AddExpenseForm (line 33)</li>
</ul>
<h2 id="heading-how-to-add-the-context-api">How to Add the Context API</h2>
<p>The Context API is what we'll use to store our global state. It's already part of the React library so no need to import/install anything else.</p>
<p>Start by creating a new folder in the <strong>src</strong> folder called <strong>context.</strong> Within this folder create a new file called <strong>AppContext.js.</strong></p>
<h3 id="heading-how-to-create-the-initial-state">How to Create the Initial State</h3>
<p>The first thing our context needs to work is an initial state. This indicates the "shape" of our state (in other words, what properties and data we have) and can be used to initialise the app with data from an API call, for example.</p>
<p>For now we'll just add some initial values. In AppContext.js, add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">budget</span>: <span class="hljs-number">2000</span>,
    <span class="hljs-attr">expenses</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">12</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'shopping'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">40</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">13</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'holiday'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">400</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">14</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'car service'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">50</span> },
    ],
};
</code></pre>
<ul>
<li>We're adding an initial budget</li>
<li>We're adding a dummy list of expenses</li>
</ul>
<blockquote>
<p>NOTE: the intialState properties do not need to have values, they can be set to empty strings, empty arrays, and so on. We're adding data for visual purposes</p>
</blockquote>
<h3 id="heading-how-to-create-the-appcontext">How to Create the AppContext</h3>
<p>Next we'll create the AppContext. This is the thing our components import and use to get the state. </p>
<p>Update AppContext.js with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">budget</span>: <span class="hljs-number">2000</span>,
    <span class="hljs-attr">expenses</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">12</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'shopping'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">40</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">13</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'holiday'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">400</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">14</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'car service'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">50</span> },
    ],
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AppContext = createContext();
</code></pre>
<p>All we've done is added a call to createContext at line (11) - thats our context object created! </p>
<h3 id="heading-how-to-create-the-appprovider">How to Create the AppProvider</h3>
<p>The provider is a component that wraps the components which we want to pass the state to. We use it in conjunction with the useReducer hook to actually store the global state.</p>
<p>Update the AppContext.js file like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">budget</span>: <span class="hljs-number">2000</span>,
    <span class="hljs-attr">expenses</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">12</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'shopping'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">40</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">13</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'holiday'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">400</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">14</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'car service'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">50</span> },
    ],
};

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

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

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
                <span class="hljs-attr">budget:</span> <span class="hljs-attr">state.budget</span>,
                <span class="hljs-attr">expenses:</span> <span class="hljs-attr">state.expenses</span>,
                <span class="hljs-attr">dispatch</span>,
            }}
        &gt;</span>
            {props.children}
        <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
    );
};
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating our Provider component (line 12)</li>
<li>Setting up the useReducer hook which will hold our state, and allow us to update the state via dispatch (NOTE we haven't created the AppReducer yet! Line 13)</li>
<li>We're returning <strong>AppContext.Provider.</strong> This has a <strong>value</strong> prop which contains the data which we allow our components to see and have access to, as well as the dispatch function that lets us update the state by dispatching actions (line 16)</li>
</ul>
<h3 id="heading-how-to-create-the-appreducer">How to Create the AppReducer</h3>
<p>Next we’ll create the AppReducer. The reducer is in charge of creating the new global state object, based on an action type and a payload. </p>
<p>Update AppContext.js with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> AppReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-attr">default</span>:
            <span class="hljs-keyword">return</span> state;
    }
};

<span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">budget</span>: <span class="hljs-number">2000</span>,
    <span class="hljs-attr">expenses</span>: [
        { <span class="hljs-attr">id</span>: <span class="hljs-number">12</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'shopping'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">40</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">13</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'holiday'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">400</span> },
        { <span class="hljs-attr">id</span>: <span class="hljs-number">14</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'car service'</span>, <span class="hljs-attr">cost</span>: <span class="hljs-number">50</span> },
    ],
};

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

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

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppContext.Provider</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
                <span class="hljs-attr">budget:</span> <span class="hljs-attr">state.budget</span>,
                <span class="hljs-attr">expenses:</span> <span class="hljs-attr">state.expenses</span>,
                <span class="hljs-attr">dispatch</span>,
            }}
        &gt;</span>
            {props.children}
        <span class="hljs-tag">&lt;/<span class="hljs-name">AppContext.Provider</span>&gt;</span></span>
    );
};
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Creating a function which accepts the current state, and an action (line 1)</li>
<li>We use a switch based on the action.type to decide how to update the state (line 2)</li>
<li>For now since we’re just getting things set up we’re just going to return the default state, and add actions later as we need them (line 3)</li>
</ul>
<p>And thats it! Our global state is now set up and ready to go. </p>
<h2 id="heading-how-to-link-appcontext-to-our-app">How to Link AppContext to our App</h2>
<p>The next step is to link our AppContext to our App component. We do this by wrapping the components which we want to pass the state to with the AppProvider.</p>
<p>Jump back into App.js and update the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> Budget <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Budget'</span>;
<span class="hljs-keyword">import</span> Remaining <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Remaining'</span>;
<span class="hljs-keyword">import</span> ExpenseTotal <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseTotal'</span>;
<span class="hljs-keyword">import</span> ExpenseList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/ExpenseList'</span>;
<span class="hljs-keyword">import</span> AddExpenseForm <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddExpenseForm'</span>;
<span class="hljs-keyword">import</span> { AppProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'./context/AppContext'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppProvider</span>&gt;</span>
            <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">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>My Budget Planner<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">Budget</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">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">Remaining</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">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseTotal</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Expenses<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseList</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>Add Expense<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row mt-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">AddExpenseForm</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">AppProvider</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>What's changed:</p>
<ul>
<li>Imported our <strong>AppProvider</strong> (line 8)</li>
<li>Nested our components in the AppProvider element (lines 12 / lines 39)</li>
</ul>
<p>Now that our components are nested within the AppProvider, they have access to <strong>value</strong> object that the AppProvider exposes. </p>
<h2 id="heading-how-to-connect-our-components-to-appcontext">How to Connect our Components to AppContext</h2>
<h3 id="heading-how-to-render-budget-from-context">How to Render Budget from Context</h3>
<p>Now we can start pulling global state values into our components. We'll start with the budget, so jump into <strong>Budget.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;

<span class="hljs-keyword">const</span> Budget = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { budget } = useContext(AppContext);

    <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">'alert alert-secondary'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Budget: £{budget}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Budget;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>We have to import <strong>AppContext</strong> from our Context (line 2)</li>
<li>We import the <strong>useContext</strong> hook, and pass our AppContext to it -  this is how a component connects to the context in order to get values from global state</li>
<li>We use <strong>destructuring</strong> to get the <strong>budget</strong> from context (line 5)</li>
<li>We're rendering the budget in our JSX (line 9)</li>
</ul>
<p>Now if you change the budget in AppContext and reload your browser, you will see the budget updates on the UI. This means our component is successfully pulling data from our context. Success! </p>
<h3 id="heading-how-to-render-expenses-from-context">How to Render Expenses from Context</h3>
<p>Now we can do something similar with the expense list. Open up <strong>ExpenseList.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ExpenseItem <span class="hljs-keyword">from</span> <span class="hljs-string">'./ExpenseItem'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;

<span class="hljs-keyword">const</span> ExpenseList = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { expenses } = useContext(AppContext);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group'</span>&gt;</span>
            {expenses.map((expense) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">ExpenseItem</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{expense.id}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{expense.name}</span> <span class="hljs-attr">cost</span>=<span class="hljs-string">{expense.cost}</span> /&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseList;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Importing our AppContext and useContext hook like before </li>
<li>We've removed the dummy list of expenses</li>
<li>We've replaced the dummy list with the expenses list we store in context</li>
</ul>
<p>Since we've already done the work to render the list of expenses, we don't have to do anything else! Refresh the browser and you'll see the list now comes from context rather than the dummy list.</p>
<p>Remember we exported expenses as part of the value object in the provider. Any component wrapped in the provider can get access to this value object, and use destructuring to get the specific value it needs.</p>
<h3 id="heading-how-to-add-a-new-expense-capturing-form-values">How to Add a New Expense - Capturing Form Values</h3>
<p>So far we've looked at how to get values from state, next we'll look at how we can dispatch actions and update the state.</p>
<p>Before we do that, we need to know the <strong>name</strong> and the <strong>cost</strong> of the new expense that the user has entered. Jump into AddExpenseForm.js and add the following:</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-keyword">const</span> AddExpenseForm = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [cost, setCost] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {

    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'name'</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'name'</span>
                        <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
                        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setName(event.target.value)}
                    &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'cost'</span>&gt;</span>Cost<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'cost'</span>
                        <span class="hljs-attr">value</span>=<span class="hljs-string">{cost}</span>
                        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setCost(event.target.value)}
                    &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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">'col-sm'</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> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-primary mt-3'</span>&gt;</span>
                        Save
                    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddExpenseForm;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Using React to control the <strong>input values</strong>. For each input field, we have a state object (lines 7 and 8)</li>
<li>When the user types into the inputs, the corresponding state values will update (lines 25 and 36)</li>
<li>When the user clicks the button, it will call an <strong>onSubmit</strong> function. This function doesn't do anything right now, but this is where we'll dispatch the action from</li>
</ul>
<p>Now we have the form values stored in state, we can dispatch an action to update the state.</p>
<h3 id="heading-how-to-add-a-new-expense-dispatching-an-action">How to Add a New Expense - Dispatching an action</h3>
<p>Update the AddExpenseForm with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

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

    <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [cost, setCost] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
        event.preventDefault();

        <span class="hljs-keyword">const</span> expense = {
            <span class="hljs-attr">id</span>: uuidv4(),
            <span class="hljs-attr">name</span>: name,
            <span class="hljs-attr">cost</span>: <span class="hljs-built_in">parseInt</span>(cost),
        };

        dispatch({
            <span class="hljs-attr">type</span>: <span class="hljs-string">'ADD_EXPENSE'</span>,
            <span class="hljs-attr">payload</span>: expense,
        });
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'name'</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'name'</span>
                        <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
                        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setName(event.target.value)}
                    &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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">'col-sm'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">'cost'</span>&gt;</span>Cost<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                        <span class="hljs-attr">required</span>=<span class="hljs-string">'required'</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span>
                        <span class="hljs-attr">className</span>=<span class="hljs-string">'form-control'</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">'cost'</span>
                        <span class="hljs-attr">value</span>=<span class="hljs-string">{cost}</span>
                        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setCost(event.target.value)}
                    &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</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">'col-sm'</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> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn btn-primary mt-3'</span>&gt;</span>
                        Save
                    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddExpenseForm;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Importing AppContext and useContext as usual </li>
<li>Getting <strong>dispatch</strong> from our global state (line 6)</li>
<li>Creating an <strong>expense object,</strong> containing the name and the cost. This is what will get dispatched as the payload, and what we'll use to update the state. We're also using the uuid package we imported earlier to create an ID. This is used to identify a given expense (line 14).</li>
<li>We're dispatching an <strong>action</strong>, with a type and our payload. The type tells the reducer how to update the state, which we'll see in a minute (line 20)</li>
</ul>
<h3 id="heading-how-to-add-a-new-expense-updating-the-reducer">How to Add a New Expense - Updating the reducer</h3>
<p>That's it from the component side. You'll notice if you run this in the browser, nothing happens. Thats because we haven't updated our reducer to handle the action and update the state. </p>
<p>Jump into <strong>AppContext.js</strong> and update the <strong>reducer</strong> function with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> AppReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_EXPENSE'</span>:
            <span class="hljs-keyword">return</span> {
                ...state,
                <span class="hljs-attr">expenses</span>: [...state.expenses, action.payload],
            };
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> state;
    }
};
</code></pre>
<p>What we're doing:</p>
<ul>
<li>We're checking the type of the action (which we get from the action variable) (line 2)</li>
<li>Adding a new case to the switch statement called "ADD_EXPENSE" (line 3)</li>
<li>Returning a new state object with the new expense taking from the payload (which we get from the action variable) (line 4)</li>
</ul>
<blockquote>
<p>When we return something from a case statement, the reducer automatically updates the state and re-renders the components, almost like magic.</p>
</blockquote>
<p>Now if you run the code, and add a new expense, you can see it gets added to the expense list!</p>
<h3 id="heading-how-to-calculate-spent-so-far">How to Calculate <code>spent so far</code></h3>
<p>The next thing we'll look at is calculating how much the user has spent so far. To do this, we'll take a total of all the expenses the user has spent and display it on the UI.</p>
<p>Open up <strong>ExpenseTotal.js</strong>  and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;

<span class="hljs-keyword">const</span> ExpenseTotal = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { expenses } = useContext(AppContext);

    <span class="hljs-keyword">const</span> totalExpenses = expenses.reduce(<span class="hljs-function">(<span class="hljs-params">total, item</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> (total += item.cost);
    }, <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">'alert alert-primary'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Spent so far: £{totalExpenses}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseTotal;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>importing our useContext and AppContext as usual </li>
<li>Taking the expenses from state (line 5)</li>
<li>Using the reduce function to get a total of all the costs and assigning this to a variable (line 7)</li>
<li>Displaying the variable in our JSX (line 13)</li>
</ul>
<p>Now whenever the user adds an expense, this causes the state to update, which will cause all components connected to the context to re-render and update themselves with new values.</p>
<p>Go ahead and try this out in the browser.</p>
<h3 id="heading-how-to-calculate-remaining">How to Calculate <code>Remaining</code></h3>
<p>Now we'll look at calculating how much budget the user has left to spend. </p>
<p>To do this, we'll get the total costs of the expenses, and subtract it from the budget. If the user goes over budget, i.e the expenses are more than the budget, we want to display a red background (as opposed to a green background). Luckily Bootstrap gives us these nice things already.</p>
<p>Open up Remaining.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;

<span class="hljs-keyword">const</span> Remaining = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { expenses, budget } = useContext(AppContext);

    <span class="hljs-keyword">const</span> totalExpenses = expenses.reduce(<span class="hljs-function">(<span class="hljs-params">total, item</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> (total = total + item.cost);
    }, <span class="hljs-number">0</span>);

    <span class="hljs-keyword">const</span> alertType = totalExpenses &gt; budget ? <span class="hljs-string">'alert-danger'</span> : <span class="hljs-string">'alert-success'</span>;

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">alert</span> ${<span class="hljs-attr">alertType</span>}`}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Remaining: £{budget - totalExpenses}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Remaining;
</code></pre>
<p>What we're doing</p>
<ul>
<li>Importing expenses and budget from Context (line 5)</li>
<li>Getting the total cost of the expenses using the reduce function (line 7)</li>
<li>Creating a variable to store the CSS classname we want to display (depending on if the user has gone over the budget or not, line 11)</li>
<li>Using a template string to create our classes (line 14)</li>
<li>Rendering the remaining budget using a subtraction (line 15)</li>
</ul>
<p>Now if you run the code in the browser, and add a bunch of expenses until the total goes over 2000, you'll see the "Remaining" component background turns to red!</p>
<h3 id="heading-how-to-remove-an-expense">How to Remove an Expense</h3>
<p>The last thing we'll look at before getting into the challenges is to remove an expense. </p>
<p>When the user clicks the little cross beside an expense, we want to dispatch an action to remove it from state. When this happens, our ExpenseList will re-render with the removed expense.</p>
<p>Jump into ExpenseItem.js and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { TiDelete } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-icons/ti'</span>;
<span class="hljs-keyword">import</span> { AppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AppContext'</span>;

<span class="hljs-keyword">const</span> ExpenseItem = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { dispatch } = useContext(AppContext);

    <span class="hljs-keyword">const</span> handleDeleteExpense = <span class="hljs-function">() =&gt;</span> {
        dispatch({
            <span class="hljs-attr">type</span>: <span class="hljs-string">'DELETE_EXPENSE'</span>,
            <span class="hljs-attr">payload</span>: props.id,
        });
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'list-group-item d-flex justify-content-between align-items-center'</span>&gt;</span>
            {props.name}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'badge badge-primary badge-pill mr-3'</span>&gt;</span>
                    £{props.cost}
                <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">TiDelete</span> <span class="hljs-attr">size</span>=<span class="hljs-string">'1.5em'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDeleteExpense}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">TiDelete</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">li</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExpenseItem;
</code></pre>
<p>What we're doing:</p>
<ul>
<li>Importing dispatch from Context, which allows us to dispatch a delete action (line 6)</li>
<li>Creating a function that gets called when the delete icon is clicked (line 8)</li>
<li>Dispatching an action. Our action contains the type (so the reducer knows how to update the state) and the payload. In this case we're passing the ID of this expense (which we get from props when we rendered the ExpenseList) (line 9)</li>
</ul>
<p>If you try this in the browser, you'll see that nothing happens. Even though we're dispatching an action, we haven't implemented the reducer logic for this action type, so it doesn't know how to update the state.</p>
<p>Jump into AppContext.js and update the reducer function with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> AppReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (action.type) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">'ADD_EXPENSE'</span>:
            <span class="hljs-keyword">return</span> {
                ...state,
                <span class="hljs-attr">expenses</span>: [...state.expenses, action.payload],
            };
        <span class="hljs-keyword">case</span> <span class="hljs-string">'DELETE_EXPENSE'</span>:
            <span class="hljs-keyword">return</span> {
                ...state,
                <span class="hljs-attr">expenses</span>: state.expenses.filter(
                    <span class="hljs-function">(<span class="hljs-params">expense</span>) =&gt;</span> expense.id !== action.payload
                ),
            };
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> state;
    }
};
</code></pre>
<p>All we're really doing here is adding a new case statement, to handle our <strong>DELETE_EXPENSE</strong> action. We're using the filter array method to remove the expense that has the ID which we received from the payload.</p>
<p>Now if you try this, you can remove an expense by clicking the delete icon. Notice how all the other components update as well. Nice!</p>
<h2 id="heading-challenges-to-try">Challenges to Try</h2>
<p>Congrats on making it this far! Now its time for you to have a go at some challenges. Remember you can see how I've done it in the GitHub source code.</p>
<h3 id="heading-allow-the-user-to-edit-the-budget">Allow the user to edit the budget</h3>
<p>You'll notice that so far we have been using a hard coded value for the budget. Your first task is to add functionality that allows the user to edit the budget. Some tips to get started:</p>
<ul>
<li>You will need to add a text input that allows the user to enter a value for their desired budget.</li>
<li>We store the budget in state, so you will need to dispatch an action with a new TYPE and a PAYLOAD that will update the state </li>
</ul>
<h3 id="heading-allow-the-user-to-search-for-an-expense">Allow the user to search for an expense</h3>
<p>If the user has many expenses, it will be difficult to find the one they are looking for. Add a way for the user to search for the expense by name. Some tips to get started:</p>
<ul>
<li>You will need to add an input field which lets the user enter a value to search for. </li>
<li>You'll have to add something to the ExpenseList component that filters the list from context based on this search value. </li>
</ul>
<h3 id="heading-thanks-for-reading">Thanks for Reading!</h3>
<p><a target="_blank" href="https://reactbeginnerprojects.com"><img src="https://www.freecodecamp.org/news/content/images/size/w1000/2021/03/Screenshot-2021-03-10-at-08.33.56.png" alt="Screenshot-2021-03-10-at-08.33.56" width="600" height="400" loading="lazy"></a> </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Movie App Tutorial - Build A Fun Portfolio Project with React and the OMBD API ]]>
                </title>
                <description>
                    <![CDATA[ In this React movie app tutorial, we're going to: Use a real API to search for movies as we type Create a "Netflix style" horizontal scroll effect Add movies to and remove them from our favourites Save our favourites to local storage to they appear ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-movie-app-tutorial/</link>
                <guid isPermaLink="false">66c8c90085ffc69fd028a828</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ portfolio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Wed, 18 Nov 2020 22:25:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/11/react-movie-app--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this React movie app tutorial, we're going to:</p>
<ul>
<li>Use a real API to search for movies as we type</li>
<li>Create a "Netflix style" horizontal scroll effect</li>
<li>Add movies to and remove them from our favourites</li>
<li>Save our favourites to local storage to they appear when the app refreshes</li>
</ul>
<h3 id="heading-this-is-what-well-build">This is what we'll build:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Nov-10-2020-07-21-23.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And here's a video walkthrough if you want to supplement your reading. </p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/jc9_Bqzy2YQ" 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>Finally, in case you get lost while following along, <a target="_blank" href="https://github.com/chrisblakely01/react-movie-app">you can grab the finished code here</a> (on GitHub).</p>
<h2 id="heading-lets-go">Let's Go!</h2>
<p>Our movie app wouldn't be any good if we didn't have any movies to display.</p>
<p>We're going to use the <a target="_blank" href="http://www.omdbapi.com/">OMDB API</a> as our source for movies. This API is free to use, and all we have to do is sign up and get an API key.</p>
<h2 id="heading-how-to-get-an-api-key">How to Get an API Key</h2>
<p>Go to <a target="_blank" href="http://www.omdbapi.com/apikey.aspx">http://www.omdbapi.com/apikey.aspx</a> and fill out the form. You should receive an email like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-07.37.11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click the activation link (highlighted in green) and you're good to go. Woohoo!</p>
<h2 id="heading-exploring-the-api-with-postman">Exploring the API with PostMan</h2>
<p>This is an optional step, so if you'd rather get into the React-y goodness feel free to jump to the next section.  </p>
<p>We're going to use Postman (<a target="_blank" href="https://www.postman.com/downloads/">download if here if you haven't got it</a>) to play with the API. </p>
<p>Fire up Postman and paste in the "OMBb API" URL you received in your email (highlighted in yellow in the image above). Click "send" and you should get some JSON back in the "body" section like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-07.53.58.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Mission success! Well, part of the mission is a success – we're only getting started here after all. But this means our URL from the email is working fine and our React App will be able to retrieve movies.</p>
<h2 id="heading-how-to-search-for-movies-by-title">How to Search for Movies by Title</h2>
<p>So far we've used the API to retrieve one movie, but what we want to do is search for "Titles containing a search term". To do this, we change the <code>i</code> query parameter to <code>s</code> like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-07.58.19.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This will query the API for all movies containing "star wars" in the title. Click "send" again, and this time you'll see the response is different:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-08.01.02.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Notice how we receive <strong>an array of items.</strong> Each item in the array contains some details about a movie (title, year and so on). We're going to take the <strong>Poster</strong> image for each object and display it in our app</p>
<h2 id="heading-how-to-set-up-a-react-project">How to Set Up a React Project</h2>
<p>Ok with that out of the way, we can get into the good stuff – creating a React project. We're going to use <code>create-react-app</code> to get us off the ground quickly.</p>
<p>Fire up a terminal and type:</p>
<p><code>npx create-create-app movie-app</code></p>
<p>When thats finished doing its thing, we're going to add Bootstrap to help us position things nicely without needing much of our own CSS. </p>
<p>Run the following commands:</p>
<pre><code class="lang-js">cd movie-app
npm install boostrap
</code></pre>
<p>Thats all we need, so go ahead and fire up the app:</p>
<p><code>npm start</code></p>
<h2 id="heading-how-to-add-movies-to-state">How to Add Movies to State</h2>
<p>The <strong>App</strong> component will hold the state for the app. That way we can keep everything organised in one place and pass different pieces of state to different components.</p>
<p>Open <code>App.js</code>, delete everything, and replace it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([        {
            <span class="hljs-string">"Title"</span>: <span class="hljs-string">"Star Wars: Episode IV - A New Hope"</span>,
            <span class="hljs-string">"Year"</span>: <span class="hljs-string">"1977"</span>,
            <span class="hljs-string">"imdbID"</span>: <span class="hljs-string">"tt0076759"</span>,
            <span class="hljs-string">"Type"</span>: <span class="hljs-string">"movie"</span>,
            <span class="hljs-string">"Poster"</span>: <span class="hljs-string">"https://m.media-amazon.com/images/M/MV5BNzVlY2MwMjktM2E4OS00Y2Y3LWE3ZjctYzhkZGM3YzA1ZWM2XkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_SX300.jpg"</span>
        },
        {
            <span class="hljs-string">"Title"</span>: <span class="hljs-string">"Star Wars: Episode V - The Empire Strikes Back"</span>,
            <span class="hljs-string">"Year"</span>: <span class="hljs-string">"1980"</span>,
            <span class="hljs-string">"imdbID"</span>: <span class="hljs-string">"tt0080684"</span>,
            <span class="hljs-string">"Type"</span>: <span class="hljs-string">"movie"</span>,
            <span class="hljs-string">"Poster"</span>: <span class="hljs-string">"https://m.media-amazon.com/images/M/MV5BYmU1NDRjNDgtMzhiMi00NjZmLTg5NGItZDNiZjU5NTU4OTE0XkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_SX300.jpg"</span>
        },
        {
            <span class="hljs-string">"Title"</span>: <span class="hljs-string">"Star Wars: Episode VI - Return of the Jedi"</span>,
            <span class="hljs-string">"Year"</span>: <span class="hljs-string">"1983"</span>,
            <span class="hljs-string">"imdbID"</span>: <span class="hljs-string">"tt0086190"</span>,
            <span class="hljs-string">"Type"</span>: <span class="hljs-string">"movie"</span>,
            <span class="hljs-string">"Poster"</span>: <span class="hljs-string">"https://m.media-amazon.com/images/M/MV5BOWZlMjFiYzgtMTUzNC00Y2IzLTk1NTMtZmNhMTczNTk0ODk1XkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg"</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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>

            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're creating a state object to hold our list of movies. This will come from the API eventually, but for now we're just going to hard code some data – which is taken from the response in Postman.</li>
<li>We're adding the CSS from Bootstrap and adding some basic markup</li>
</ul>
<p>If you save/run the app, you'll see that even though we've set up some state, we aren't rendering anything yet – so the screen will be blank.</p>
<h2 id="heading-how-to-create-a-movielist-component">How to Create a MovieList Component</h2>
<p>Ah our first component! We're going to create a <strong>MovieList</strong> component to display the list of movies that comes back in the search request.</p>
<p>Create a new folder call <strong>components</strong> under the <strong>src</strong> folder. Create a new file in the components folder called <strong>MovieList.js:</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-08.21.57.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Open up MovieList.js and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MovieList = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            {props.movies.map((movie, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'image-container d-flex justify-content-start m-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{movie.Poster}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'movie'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MovieList;
</code></pre>
<ul>
<li>We'll pass in a list of movies as <strong>props</strong></li>
<li>We'll use the map function to <strong>loop</strong> over these movies</li>
<li>For each movie we'll display an <strong>image</strong> using the Poster URL as the image source</li>
</ul>
<h2 id="heading-how-to-render-our-movielist">How to Render our MovieList</h2>
<p>Just one more step before we see stuff working in the browser - are you excited?! </p>
<p>Jump back into <strong>App.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([
        {
            <span class="hljs-attr">Title</span>: <span class="hljs-string">'Star Wars: Episode IV - A New Hope'</span>,
            <span class="hljs-attr">Year</span>: <span class="hljs-string">'1977'</span>,
            <span class="hljs-attr">imdbID</span>: <span class="hljs-string">'tt0076759'</span>,
            <span class="hljs-attr">Type</span>: <span class="hljs-string">'movie'</span>,
            <span class="hljs-attr">Poster</span>:
                <span class="hljs-string">'https://m.media-amazon.com/images/M/MV5BNzVlY2MwMjktM2E4OS00Y2Y3LWE3ZjctYzhkZGM3YzA1ZWM2XkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_SX300.jpg'</span>,
        },
        {
            <span class="hljs-attr">Title</span>: <span class="hljs-string">'Star Wars: Episode V - The Empire Strikes Back'</span>,
            <span class="hljs-attr">Year</span>: <span class="hljs-string">'1980'</span>,
            <span class="hljs-attr">imdbID</span>: <span class="hljs-string">'tt0080684'</span>,
            <span class="hljs-attr">Type</span>: <span class="hljs-string">'movie'</span>,
            <span class="hljs-attr">Poster</span>:
                <span class="hljs-string">'https://m.media-amazon.com/images/M/MV5BYmU1NDRjNDgtMzhiMi00NjZmLTg5NGItZDNiZjU5NTU4OTE0XkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_SX300.jpg'</span>,
        },
        {
            <span class="hljs-attr">Title</span>: <span class="hljs-string">'Star Wars: Episode VI - Return of the Jedi'</span>,
            <span class="hljs-attr">Year</span>: <span class="hljs-string">'1983'</span>,
            <span class="hljs-attr">imdbID</span>: <span class="hljs-string">'tt0086190'</span>,
            <span class="hljs-attr">Type</span>: <span class="hljs-string">'movie'</span>,
            <span class="hljs-attr">Poster</span>:
                <span class="hljs-string">'https://m.media-amazon.com/images/M/MV5BOWZlMjFiYzgtMTUzNC00Y2IzLTk1NTMtZmNhMTczNTk0ODk1XkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg'</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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're importing the MovieList component (line 4 in your IDE)</li>
<li>We're <strong>rendering</strong> the MovieList and passing the movies we stored in state as props (line 37 in your IDE)</li>
</ul>
<p>Save and run the app, and then if you go to the browser you should see the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-10-at-08.30.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>These movies are taking from our <strong>movies</strong> state object in App.js</em></p>
<p>We have some movie posters. Marvelous! </p>
<h2 id="heading-how-to-add-a-call-to-the-api">How to Add a Call to the API</h2>
<p>Now that we know our app is capable of rendering the movies we receive from the API, we can add logic to make a request to get Movies and render these on the screen. </p>
<p>Update <strong>App.js</strong> with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=star wars&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're removing the hardcoded movies from our movie state value (line 7 in your IDE)</li>
<li>We've added a function that calls the API. This uses the Fetch API (line 9 in your IDE)</li>
<li>We are hardcoding a search value for now – later we'll add an input that the user can type a search value into (line 10 in your IDE)</li>
<li>If we get any movies back in the search, we're going to set this to our movie state </li>
<li>We're using a <strong>useEffect</strong> to make sure the API call only happens when the app loads for the first time (line 20 in your IDE)</li>
</ul>
<p>Since we already pass the <code>movie</code> state value to the <code>MovieList</code> as props, this works automatically without us having to change our JSX. How nice!</p>
<h2 id="heading-how-to-add-horizontal-scroll">How to Add Horizontal Scroll</h2>
<p>While we're here we're going to add the fancy horizontal scroll effect and a dark background – Netflix style.</p>
<p>Go to <code>App.css</code> and delete everything that's there. Then add the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#141414</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ffffff</span>;
}

<span class="hljs-selector-class">.movie-app</span> &gt; <span class="hljs-selector-class">.row</span> {
    <span class="hljs-attribute">overflow-x</span>: auto;
    <span class="hljs-attribute">flex-wrap</span>: nowrap;
}
</code></pre>
<p>Thats it! Try scrolling horizontally through the movies in the browser.</p>
<h2 id="heading-how-to-add-a-heading-and-search-input">How to Add a Heading and Search input</h2>
<p>So far we've been using hardcoded search values, but this might not please the non Star Wars fans.</p>
<p>Next we'll add a heading and a search input that lets the user search for whatever they want.</p>
<h3 id="heading-how-to-add-the-heading">How to add the Heading</h3>
<p>Add a new component to the <strong>components</strong> folder called <strong>MovieListHeading.js.</strong> Open it up and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MovieListHeading = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'col'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{props.heading}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MovieListHeading;
</code></pre>
<ul>
<li>This accepts a <strong>heading prop</strong> which gets rendered within a Bootstrap column</li>
<li>This allows us to reuse this later</li>
</ul>
<h3 id="heading-how-to-add-the-search-input">How to add the Search Input</h3>
<p>Add a new component to the <strong>components</strong> folder called <strong>SearchBox.js.</strong> Open it up and add the following:</p>
<pre><code class="lang-react">import React from 'react';

const SearchBox = (props) =&gt; {
    return (
        &lt;div className='col col-sm-4'&gt;
            &lt;input
                className='form-control'
                value={props.value}
                onChange={(event) =&gt; props.setSearchValue(event.target.value)}
                placeholder='Type to search...'
            &gt;&lt;/input&gt;
        &lt;/div&gt;
    );
};

export default SearchBox;
</code></pre>
<ul>
<li>This renders an input </li>
<li>Takes a value from <strong>props</strong>, and when the user types, calls a function which updates the value. This is also taken from props.</li>
</ul>
<h3 id="heading-how-to-save-the-search-input-to-state">How to save the Search Input to state</h3>
<p>Now that we have some new components, we need to know what the user has typed so that we can send it to the API. Update <strong>App.js</strong> with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=star wars&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're adding a new <strong>state value</strong> to store what the user types (line 10 in your IDE)</li>
<li>We're importing our components (lines 5/6 in your IDE)</li>
<li>We're adding a new "row" that holds our <strong>MovieListHeading</strong> and <strong>Searchbox</strong> components (line 29 in your IDE)</li>
<li>And we're passing the <strong>searchValue</strong> value and the <strong>setSearchValue</strong> function to the <strong>SearchBox</strong> component (line 31)</li>
</ul>
<p>By saving the state of the input in App.js, it makes it easy for us to pass the search value to the <code>getMovieRequest</code> function.</p>
<h3 id="heading-how-to-call-the-api-when-the-search-value-changes">How to call the API when the Search Value changes</h3>
<p>Now that we know what the user has typed, we need to call the API with this value. Update App.js with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're updating our <strong>getMovieRequest</strong> function to accept a parameter: <strong>searchValue</strong> (line 12 in your IDE)</li>
<li>We're passing this value to the request using a template string (line 13 in your IDE)</li>
<li>We're updating the <strong>useEffect</strong> hook to run whenever the <strong>searchValue changes</strong> (line 25 in your IDE)</li>
<li>When the useEffect hooks runs, it passes the new <strong>searchValue</strong> to our <strong>getMovieRequest</strong> function (line 24 in your IDE)</li>
<li>This does a call to the API and updates the state if we get results as usual</li>
</ul>
<p>Try this in the browser – and you'll see the results update in real time.</p>
<h2 id="heading-how-to-add-favourites">How to Add Favourites</h2>
<p>Being able to search for movies is nice and all, but how are we supposed to remember to watch all these fantastic films? By adding them to favourites, of course! </p>
<p>We'll add a nice "zooming" effect that shows an "Add to Favourites" button when the user hovers over the poster, like you see below. </p>
<p>We'll also add logic to add/display any favourite movies the user selects:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Nov-10-2020-15-47-40.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-add-the-overlay">How to add the Overlay</h3>
<p>We'll start by adding the overlay and zooming effect. Go to <strong>MovieList.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MovieList = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            {props.movies.map((movie, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'image-container d-flex justify-content-start m-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{movie.Poster}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'movie'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'overlay d-flex align-items-center justify-content-center'</span>&gt;</span>
                        Add to Favourites
                    <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;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MovieList;
</code></pre>
<ul>
<li>We're adding a new class to the parent div: <strong>image-container.</strong> This will allow us to add the zoom effect (line 7 in your IDE)</li>
<li>We're adding a new div which will be the overlay. We'll hide this div initially and show it when the user hovers over (line 9 in your IDE)</li>
<li>We're adding some text (line 10 in your IDE)</li>
</ul>
<p>Now if you save and run this, nothing will happen. We need to add some CSS for the magic to happen. Go to <strong>App.css and add the following to the file:</strong></p>
<pre><code>
.image-container {
    <span class="hljs-attr">position</span>: relative;
    transition: transform <span class="hljs-number">0.2</span>s;
}

.image-container:hover {
    <span class="hljs-attr">cursor</span>: pointer;
    transform: scale(<span class="hljs-number">1.1</span>);
}

.image-container:hover .overlay {
    <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>;
}

.overlay {
    <span class="hljs-attr">position</span>: absolute;
    background: rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.8</span>);
    width: <span class="hljs-number">100</span>%;
    transition: <span class="hljs-number">0.5</span>s ease;
    opacity: <span class="hljs-number">0</span>;
    bottom: <span class="hljs-number">0</span>;
    font-size: <span class="hljs-number">20</span>px;
    padding: <span class="hljs-number">20</span>px;
    text-align: center;
}
</code></pre><ul>
<li>We're adding a transition effect to the image container to "scale" it when the user hovers over (giving us the zoom effect)</li>
<li>We're adding some styling to the <strong>overlay</strong> which is hidden initially</li>
<li>We're increasing the <strong>opacity</strong> (that is, showing the overlay) when the user hovers over</li>
</ul>
<p>If you run this in the browser, you can see the image "zooms" and the overlay appears when you hover over. Neat!</p>
<h3 id="heading-how-to-create-the-add-to-favourites-component">How to create the "Add to Favourites" component</h3>
<p>Next we're going to create an "Add to Favourites" component that we pass to the MovieList which we'll then render in the overlay. </p>
<p>Create a new file in the <strong>components</strong> folder called <strong>AddToFavourites.js.</strong> Add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> AddFavourite = <span class="hljs-function">() =&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">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mr-2'</span>&gt;</span>Add to Favourites<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
                <span class="hljs-attr">width</span>=<span class="hljs-string">'1em'</span>
                <span class="hljs-attr">height</span>=<span class="hljs-string">'1em'</span>
                <span class="hljs-attr">viewBox</span>=<span class="hljs-string">'0 0 16 16'</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">'bi bi-heart-fill'</span>
                <span class="hljs-attr">fill</span>=<span class="hljs-string">'red'</span>
                <span class="hljs-attr">xmlns</span>=<span class="hljs-string">'http://www.w3.org/2000/svg'</span>
            &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                    <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">'evenodd'</span>
                    <span class="hljs-attr">d</span>=<span class="hljs-string">'M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z'</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddFavourite;
</code></pre>
<p>This will return the text "Add to Favourites" and a "Heart" icon (taken from www.icons.getboostrap.com).</p>
<p>Next we're going to import this component into <strong>App.js</strong> and pass it to our <strong>MovieList component</strong>. Update App.js with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;
<span class="hljs-keyword">import</span> AddFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddFavourites'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span> <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're importing our new <strong>AddFavourites</strong> component (line 7 in your IDE)</li>
<li>We're passing this as a <strong>prop</strong> (favouriteComponent) to our <strong>MovieList</strong> component (line 35)</li>
</ul>
<p>Now that our MovieList component accepts this component as a prop, we can render it in our overlay</p>
<p>Remember that React components are just functions - so we can pass them around like we do normal functions!</p>
<p>Open up <strong>MovieList.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MovieList = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> FavouriteComponent = props.favouriteComponent;
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            {props.movies.map((movie, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'image-container d-flex justify-content-start m-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{movie.Poster}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'movie'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'overlay d-flex align-items-center justify-content-center'</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">FavouriteComponent</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MovieList;
</code></pre>
<ul>
<li>We're taking our <strong>favouriteComponent</strong> from props and assigning it to a variable. This lets us use it as a react component (line 4 in your IDE)</li>
<li>We're rendering our <strong>favouriteComponent</strong> in the overlay (line 15 in your IDE)</li>
</ul>
<p>This approach lets us customize what gets rendered in the overlay. We can pass any react component and the MovieList component will render it. This makes our MovieList component reusable.</p>
<h3 id="heading-how-to-save-favourites-to-state">How to save favourites to state</h3>
<p>So we have our favourites component in place, and although it looks nice, it doesn't do anything yet. </p>
<p>When the user clicks the "Add to Favourites" component, we want to take the movie they clicked and save it into a new state object called <strong>favourites</strong>. We'll then render this list in the UI.</p>
<p>Open up <strong>App.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;
<span class="hljs-keyword">import</span> AddFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddFavourites'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [favourites, setFavourites] = useState([]);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

    <span class="hljs-keyword">const</span> addFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = [...favourites, movie];
        setFavourites(newFavouriteList);
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{addFavouriteMovie}</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're adding a new state object to hold our favourites. We'll add whatever movie the user clicked to this array (line 12 in your IDE)</li>
<li>We're creating a function called <strong>addFavouriteMovie,</strong> which accepts a <strong>movie</strong>. This takes the current favourites array, copies it, adds the new movie to it, and saves everything back into state (line 25 in your IDE)</li>
<li>We're passing this function as a <strong>prop (handleFavouritesClick)</strong> to our <strong>MovieList</strong> component (line 44 in your IDE)</li>
</ul>
<p>Now that we have our state object, and a way to update that state object, we need to call this from our <strong>favouritesComponent</strong> in <strong>MovieList</strong>.</p>
<p>Open up <strong>MovieList.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MovieList = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> FavouriteComponent = props.favouriteComponent;

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            {props.movies.map((movie, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'image-container d-flex justify-content-start m-3'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{movie.Poster}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'movie'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> props.handleFavouritesClick(movie)}
                        className='overlay d-flex align-items-center justify-content-center'
                    &gt;
                        <span class="hljs-tag">&lt;<span class="hljs-name">FavouriteComponent</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MovieList;
</code></pre>
<ul>
<li>All we're doing here is taking the <strong>handleFavouritesClick</strong> function from props and adding it to an <strong>onClick</strong> property in the overlay </li>
<li>We're passing the current movie the map function is currently on to the handleFavouritesClick function</li>
</ul>
<p>Now if you run the app, click "Add to Favourites" for any movie, and open up the React dev tools (in Chrome) you'll see it updates in state. </p>
<p>Unfortunately the hooks aren't named the same as what we called them, but we can guess which one it is:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-11-at-05.38.48.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-render-favourite-movies">How to render Favourite movies</h3>
<p>Things are looking good so far. we have the ability to save things to favourites, but haven't actually displayed them yet.</p>
<p>We're going to reuse the <strong>MovieList component</strong> to display our favourites. How fancy!</p>
<p>Open up <strong>App.js</strong> and update it with the following: </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;
<span class="hljs-keyword">import</span> AddFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddFavourites'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [favourites, setFavourites] = useState([]);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

    <span class="hljs-keyword">const</span> addFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = [...favourites, movie];
        setFavourites(newFavouriteList);
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{addFavouriteMovie}</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">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Favourites'</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span> <span class="hljs-attr">movies</span>=<span class="hljs-string">{favourites}</span> <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're adding a new <strong>row</strong> and within it, adding a new heading using the <strong>MovieListHeading</strong> component (line 47 in your IDE)</li>
<li>We're adding a new row below that, and rending our <strong>favourites</strong> using the <strong>MovieList</strong> component (line 51)</li>
</ul>
<p>This is an example of how to create a reusable component. If a component uses the similar logic but displays different data for different situations, you can probably reuse it.</p>
<p>Fire this up in the browser and everything should work:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Nov-11-2020-05-49-25.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-remove-favourites">How to Remove Favourites</h2>
<p>Next we want to add the ability to remove movies from favourites. We'll take a similar approach we did to adding favourites:</p>
<ul>
<li>Create a <strong>remove component</strong> that we pass to our <strong>MovieList</strong>, which gets rendered in the overlay</li>
<li>Create a function called <strong>clicked</strong> to remove the clicked movie from state.</li>
<li>Pass a function to handle the <strong>onClick</strong> event when the user clicks the remove component</li>
</ul>
<h3 id="heading-how-to-create-the-removefavourites-component">How to create the RemoveFavourites component</h3>
<p>Create a new file in the components folder called <strong>RemoveFavourites.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> RemoveFavourites = <span class="hljs-function">() =&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">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mr-2'</span>&gt;</span>Remove from favourites<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
                <span class="hljs-attr">width</span>=<span class="hljs-string">'1em'</span>
                <span class="hljs-attr">height</span>=<span class="hljs-string">'1em'</span>
                <span class="hljs-attr">viewBox</span>=<span class="hljs-string">'0 0 16 16'</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">'bi bi-x-square'</span>
                <span class="hljs-attr">fill</span>=<span class="hljs-string">'currentColor'</span>
                <span class="hljs-attr">xmlns</span>=<span class="hljs-string">'http://www.w3.org/2000/svg'</span>
            &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                    <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">'evenodd'</span>
                    <span class="hljs-attr">d</span>=<span class="hljs-string">'M14 1H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z'</span>
                /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                    <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">'evenodd'</span>
                    <span class="hljs-attr">d</span>=<span class="hljs-string">'M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z'</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> RemoveFavourites;
</code></pre>
<ul>
<li>We're adding the text "remove from favourites" (line 6 in your IDE)</li>
<li>We're adding a "remove" icon which we get from icons.getbootrap.com (line 7 in your IDE)</li>
</ul>
<h3 id="heading-how-to-remove-favourites-from-state">How to remove favourites from state</h3>
<p>Similar to what we did before, we need to write a function that <strong>removes</strong> a selected movie from our <strong>favourites state.</strong></p>
<p>Open <strong>App.js</strong> and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;
<span class="hljs-keyword">import</span> AddFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddFavourites'</span>;
<span class="hljs-keyword">import</span> RemoveFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/RemoveFavourites'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [favourites, setFavourites] = useState([]);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

    <span class="hljs-keyword">const</span> addFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = [...favourites, movie];
        setFavourites(newFavouriteList);
    };

    <span class="hljs-keyword">const</span> removeFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = favourites.filter(
            <span class="hljs-function">(<span class="hljs-params">favourite</span>) =&gt;</span> favourite.imdbID !== movie.imdbID
        );

        setFavourites(newFavouriteList);
    };

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

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{addFavouriteMovie}</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">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Favourites'</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{favourites}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{removeFavouriteMovie}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{RemoveFavourites}</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're importing our <strong>RemoveFavourites</strong> component (line 8 in your IDE)</li>
<li>We're creating a function called <strong>removeFavouriteMovie</strong> to remove a given movie from our favourites state (line 31 in your IDE)</li>
<li>To remove we're using the filter function. This returns a new version of the <strong>favourites</strong> array that does not include the movie we wish to remove</li>
<li>We're passing our <strong>RemoveFavourites</strong> component and our <strong>removeFavouriteMovie</strong> function to our <strong>MovieList</strong> component (line 60 in your IDE)</li>
</ul>
<p>Because we already coded our MovieList component to accept a component to render and a function to call, everything just works!</p>
<p>Now if you run this in your browser you should be able to remove favourites:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Nov-11-2020-06-09-31.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-save-or-remove-movies-from-local-storage">How to Save or Remove Movies from Local Storage</h2>
<p>The last thing we're going to do is save to local storage. This lets us persist our favourite movies when the page reloads or if we open the app in a different window.</p>
<p>We'll save our favourites to <strong>local storage</strong> when something changes, and we'll retrieve our <strong>favourites</strong> from local storage when the app loads, saving this to or <strong>favourites</strong> state.</p>
<p>Open <strong>App.js</strong> for the final time and update it with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> MovieList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieList'</span>;
<span class="hljs-keyword">import</span> MovieListHeading <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/MovieListHeading'</span>;
<span class="hljs-keyword">import</span> SearchBox <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/SearchBox'</span>;
<span class="hljs-keyword">import</span> AddFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/AddFavourites'</span>;
<span class="hljs-keyword">import</span> RemoveFavourites <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/RemoveFavourites'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [movies, setMovies] = useState([]);
    <span class="hljs-keyword">const</span> [favourites, setFavourites] = useState([]);
    <span class="hljs-keyword">const</span> [searchValue, setSearchValue] = useState(<span class="hljs-string">''</span>);

    <span class="hljs-keyword">const</span> getMovieRequest = <span class="hljs-keyword">async</span> (searchValue) =&gt; {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`http://www.omdbapi.com/?s=<span class="hljs-subst">${searchValue}</span>&amp;apikey=263d22d8`</span>;

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

        <span class="hljs-keyword">if</span> (responseJson.Search) {
            setMovies(responseJson.Search);
        }
    };

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

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> movieFavourites = <span class="hljs-built_in">JSON</span>.parse(
            <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'react-movie-app-favourites'</span>)
        );

        setFavourites(movieFavourites);
    }, []);

    <span class="hljs-keyword">const</span> saveToLocalStorage = <span class="hljs-function">(<span class="hljs-params">items</span>) =&gt;</span> {
        <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'react-movie-app-favourites'</span>, <span class="hljs-built_in">JSON</span>.stringify(items));
    };

    <span class="hljs-keyword">const</span> addFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = [...favourites, movie];
        setFavourites(newFavouriteList);
        saveToLocalStorage(newFavouriteList);
    };

    <span class="hljs-keyword">const</span> removeFavouriteMovie = <span class="hljs-function">(<span class="hljs-params">movie</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> newFavouriteList = favourites.filter(
            <span class="hljs-function">(<span class="hljs-params">favourite</span>) =&gt;</span> favourite.imdbID !== movie.imdbID
        );

        setFavourites(newFavouriteList);
        saveToLocalStorage(newFavouriteList);
    };

    <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-fluid movie-app'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Movies'</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">SearchBox</span> <span class="hljs-attr">searchValue</span>=<span class="hljs-string">{searchValue}</span> <span class="hljs-attr">setSearchValue</span>=<span class="hljs-string">{setSearchValue}</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{movies}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{addFavouriteMovie}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{AddFavourites}</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">'row d-flex align-items-center mt-4 mb-4'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieListHeading</span> <span class="hljs-attr">heading</span>=<span class="hljs-string">'Favourites'</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">'row'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MovieList</span>
                    <span class="hljs-attr">movies</span>=<span class="hljs-string">{favourites}</span>
                    <span class="hljs-attr">handleFavouritesClick</span>=<span class="hljs-string">{removeFavouriteMovie}</span>
                    <span class="hljs-attr">favouriteComponent</span>=<span class="hljs-string">{RemoveFavourites}</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li>We're adding a function called <strong>saveToLocalStorage.</strong> This function takes a list of items, and saves them to local storage against a <strong>key.</strong> In this case the key is <strong>react-movie-app-favourites.</strong> (line 38 in your IDE)</li>
<li>We're saving to local storage when we <strong>add a favourite movie</strong> (line 45 in your IDE)</li>
<li>We're saving to local storage when we <strong>remove a favourite movie</strong> (line 54 in your IDE)</li>
<li>We're using the <strong>useEffect</strong> hook to retrieve favourites from local storage when the app loads, and we're setting this to state (line 30 in your IDE)</li>
</ul>
<p>Fire this up in your browser and you should be able to save favourite movies - even if you close the browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Nov-11-2020-06-21-58.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-end-what-next">The End - What Next?</h2>
<p>Thanks for reading, and more importantly - congrats on making it to the end! </p>
<p>If you enjoyed this article, make sure to check out <a target="_blank" href="https://www.freecodecamp.org/news/p/e8fd6f73-03c1-48b3-8988-b3a47691577b/reactbeginnerprojects.com">reactbeginnerprojects.com</a>. You'll find a bunch of free projects you can try out to learn the key skills you'll need to land a job as a React developer and boost your portfolio.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Shopping List Using React Hooks (w/ Starter Code and Video Walkthrough) ]]>
                </title>
                <description>
                    <![CDATA[ What we're building In this beginner React tutorial, we're going to build a shopping app. We'll work with complex state objects, update parts of the state, and use existing state to calculate new state.  Check it out here: Try it yourself If you wan... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-shopping-list-using-react-hooks-w-starter-code-and-video-walkthrough/</link>
                <guid isPermaLink="false">66c8c8ecfe21816c4cb75d1b</guid>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Mon, 12 Oct 2020 20:16:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/Copy-of-Build-a-Temperature-control-App--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-were-building">What we're building</h2>
<p>In this beginner React tutorial, we're going to build a shopping app. We'll work with complex state objects, update parts of the state, and use existing state to calculate new state. </p>
<p>Check it out here:</p>
<p><img src="https://jschris.com/41168097024a0b0e7b306a91023114b8/project.gif" alt="project" width="600" height="400" loading="lazy"></p>
<h2 id="heading-try-it-yourself">Try it yourself</h2>
<p>If you want to have a go yourself first, here are the scenarios (you can also grab the starter code below):</p>
<ul>
<li>The user should be able to add new items to the list, by typing into the input and clicking the "+" symbol</li>
<li>The user should be able to increase/decrease the quantities of a particular item</li>
<li>The total should show the total quantity for all the items in the list</li>
</ul>
<h2 id="heading-video-walkthrough">Video walkthrough</h2>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/_N6LQd6Y2UY" title="Embedded content" loading="lazy"></iframe></div>

<h2 id="heading-starter-code">Starter Code</h2>
<p><a target="_blank" href="https://github.com/chrisblakely01/simple-shopping-list">Grab it over on GitHub here</a></p>
<h2 id="heading-how-to-display-a-list-of-items">How to display a list of items</h2>
<p>The first thing we're going to do is display a list of items. If you working with the starter code, you'll see that I've added a state object:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [items, setItems] = useState([]);
</code></pre>
<p>We're going to initialise this with an array of objects. We'll then use the map function to loop over this list and display the items. </p>
<p>Replace the above line with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [items, setItems] = useState([
    { <span class="hljs-attr">itemName</span>: <span class="hljs-string">'item 1'</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">isSelected</span>: <span class="hljs-literal">false</span> },
    { <span class="hljs-attr">itemName</span>: <span class="hljs-string">'item 2'</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">isSelected</span>: <span class="hljs-literal">true</span> },
    { <span class="hljs-attr">itemName</span>: <span class="hljs-string">'item 3'</span>, <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">isSelected</span>: <span class="hljs-literal">false</span> },
]);
</code></pre>
<p>You'll notice that each item in the array is an <strong>object</strong>. This object represents each item (or row) and holds the things we'll need to display:</p>
<ul>
<li>The item's name</li>
<li>The quantity</li>
<li>A flag which we'll use to display a "tick" or "empty circle"</li>
</ul>
<blockquote>
<p>The reason we put this list in state as an array is because the list will change. When we want to change the list, we just add things to or remove them from the array and React will automatically update the UI for us.</p>
</blockquote>
<p>Ok now we just have to add a map function to our JSX and loop over this array and display the properties on the UI. </p>
<p>Replace the <strong>item list div</strong> with the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'item-list'</span>&gt;
    {items.map(<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</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">'item-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'item-name'</span>&gt;</span>
                {item.isSelected ? (
                    <span class="hljs-tag">&lt;&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faCheckCircle}</span> /&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'completed'</span>&gt;</span>{item.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                    <span class="hljs-tag">&lt;/&gt;</span>
                ) : (
                    <span class="hljs-tag">&lt;&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faCircle}</span> /&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                    <span class="hljs-tag">&lt;/&gt;</span></span>
                )}
            &lt;/div&gt;
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'quantity'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faChevronLeft}</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span> {item.quantity} <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faChevronRight}</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        &lt;/div&gt;
    ))}
&lt;/div&gt;
</code></pre>
<p>Let's walk through this.</p>
<ul>
<li><p>We've introduced the map function. It will loop over the items in the <strong>items</strong> array and display a bunch of JSX for each <strong>item</strong>. Remember, the map function gives us the <strong>current object it is currently on as a variable</strong> so we can access its properties.</p>
</li>
<li><p>We're using a ternary to check the <strong>item.isSelected</strong> variable. If the variable is true, we display a "tick" with a strikethrough. If the value is false, we display an "empty circle" along with the item name.</p>
</li>
<li><p>We're also displaying the quantity for that particular item.</p>
</li>
</ul>
<h2 id="heading-how-to-store-what-the-user-types-in-state">How to store what the user types in state</h2>
<p>Now that we've got some items displaying, we'll let the user add some items to the list. It wouldn't be a very good shopping list if they couldn't add things to it!</p>
<p>You'll see in the starter code that I've included an input:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'add-item-box'</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'add-item-input'</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Add an item...'</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faPlus}</span> /&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>At the moment this doesn't do very much. We need to give control to React so that we can easily work with the value the user typed. </p>
<p>To do this, we'll create a new state value to hold the value of what the user has typed, and we'll add an <strong>onChange event</strong> to change this value.</p>
<p>Add a new state object, and initialise it to an empty string:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);
</code></pre>
<p>Now within the input, add a <strong>value</strong> and an <strong>onChange</strong> function like so:</p>
<pre><code class="lang-jsx">&lt;input value={inputValue} onChange={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> setInputValue(event.target.value)} className=<span class="hljs-string">'add-item-input'</span> placeholder=<span class="hljs-string">'Add an item...'</span> /&gt;
</code></pre>
<p>Whenever the user types, the <strong>onChange</strong> event gets called. React passes in the <strong>event</strong> automatically for us, so we can get the value the user has typed from this. </p>
<p>We then take this value and call the <strong>setInputValue</strong> to set what the user has typed into state.</p>
<p>We then set the value of the input to be whatever value is stored in the <strong>inputValue</strong> state variable.</p>
<h2 id="heading-how-to-add-a-new-item-to-the-list">How to add a new item to the list</h2>
<p>Now it makes sense to add the value the user has typed to the list. Since we know the current list, and we know the thing the user typed (we stuck everything in state!) all we have to do is mash these things together. </p>
<p>In order words, we're going to add the <strong>inputValue</strong> to the <strong>items</strong> array.</p>
<p>Start by creating a new function, which will get called when the user clicks the "+" icon:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAddButtonClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> newItem = {
        <span class="hljs-attr">itemName</span>: inputValue,
        <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span>,
        <span class="hljs-attr">isSelected</span>: <span class="hljs-literal">false</span>,
    };

    <span class="hljs-keyword">const</span> newItems = [...items, newItem];

    setItems(newItems);
    setInputValue(<span class="hljs-string">''</span>);
};
</code></pre>
<p>What does this is:</p>
<ul>
<li><p>Creates a new object called <strong>newItem</strong> which is what gets pushed to the array. We set the <strong>itemName</strong> to whatever the <strong>inputValue</strong> is, we default the <strong>quantity</strong> to <strong>1</strong>, and default the <strong>isSelected</strong> boolean to <strong>false</strong></p>
</li>
<li><p>Copies the existing array (we do this to avoid mutating state), and adds our <strong>newItem object</strong> to the end</p>
</li>
<li><p>Pushes the new array back into state</p>
</li>
<li><p>Finally, resets the <strong>inputValue</strong> to empty string so that the user can type and add more stuff</p>
</li>
</ul>
<p>Now that we've got a function, we just have to wire it up to our button:</p>
<pre><code class="lang-jsx">&lt;FontAwesomeIcon icon={faPlus} onClick={<span class="hljs-function">() =&gt;</span> handleAddButtonClick()} /&gt;
</code></pre>
<p>If you run the code, type stuff into the input, and click the "plus" icon, it should get added to the list. Woohooo!</p>
<h2 id="heading-how-to-toggle-an-item">How to toggle an item</h2>
<p>Now we'll look at how we can toggle an item to indicate that it was selected. We know that each item in the array/list has an *<em>isSelected</em> variable, so all we have to do is update this when an item is clicked.</p>
<p>Create a new function like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> toggleComplete = <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> newItems = [...items];

    newItems[index].isSelected = !newItems[index].isSelected;

    setItems(newItems);
};
</code></pre>
<p>This takes an <strong>index</strong> as a parementer. The index is given to us by the map function, and indicates what <em>position</em> in the array we're currently on. </p>
<p>We then use this index to get the object from the array, and set the <strong>isSelected</strong> variable to the opposite of what it currently is.</p>
<p>We then put the updated items into state. This causes React to rerender the component and render either a "checked circle" or an "empty circle" for each item depending on the this flag (remember we wrote the ternery logic for this earlier).</p>
<p>To get this all to work we just need to call <strong>toggleComplete</strong> when the user clicks the circle:</p>
<p>Update the <strong>itemName</strong> div like so:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'item-name'</span> onClick={<span class="hljs-function">() =&gt;</span> toggleComplete(index)}&gt;
    <span class="hljs-comment">// ...other code</span>
&lt;/div&gt;
</code></pre>
<p>Note we pass in the index which we get from the map function. This tells us the current position in the array we're currently on.</p>
<p>Run the code and you should be able to "select" and item. Success!</p>
<h2 id="heading-how-to-update-the-quantities">How to update the quantities</h2>
<p>We're going to take a similar approach to update the quantities. We'll start with the increase quantity. Add a function like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleQuantityIncrease = <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> newItems = [...items];

    newItems[index].quantity++;

    setItems(newItems);
};
</code></pre>
<p>You'll notice this is similar to the <strong>toggleComplete</strong> function:</p>
<ul>
<li>We use the index to get the item/object from the array</li>
<li>We increase the quantity</li>
<li>We put everything back into state</li>
</ul>
<p>Now we just need to update our button to call this function:</p>
<pre><code class="lang-jsx">&lt;button&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{faChevronRight}</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleQuantityIncrease(index)} /&gt;</span>
&lt;/button&gt;
</code></pre>
<p>Try this, and you should be able to click the "right chevron" and the quantity should go up.</p>
<p>Handling the <strong>decrease quantity</strong> will be similar again. Create a function like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleQuantityDecrease = <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> newItems = [...items];

    newItems[index].quantity--;

    setItems(newItems);
};
</code></pre>
<p>What we're doing:</p>
<ul>
<li>We use the index to get the item/object from the array</li>
<li>We decrese the quantity</li>
<li>We put everything back into state</li>
</ul>
<h2 id="heading-how-to-calculate-the-total-quantity">How to calculate the total quantity</h2>
<p>Ok, our app is looking good. The last thing we need to do is update the total quantity at the bottom. </p>
<p>The first thing we're going to do is create a state value. This will be used to hold/display the total quantities:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [totalItemCount, setTotalItemCount] = useState(<span class="hljs-number">6</span>);
</code></pre>
<p>We'll default this to <strong>6</strong> as this is what the quantities in the initial list add up to.</p>
<p>Next we'll render this in our JSX:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'total'</span>&gt;Total: {totalItemCount}&lt;/div&gt;
</code></pre>
<p>Everything will look the same so far. That's because we haven't written any logic to update the state yet. We'll create a new function:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> calculateTotal = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> totalItemCount = items.reduce(<span class="hljs-function">(<span class="hljs-params">total, item</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> total + item.quantity;
    }, <span class="hljs-number">0</span>);

    setTotalItemCount(totalItemCount);
};
</code></pre>
<p>This uses the <strong>reduce</strong> function to add up all the quantities in our items array.</p>
<p>Lastly, all we have to do is call this function whenever the user increases/decreases the quantity, or adds a new item. Update the respective functions like so:</p>
<pre><code class="lang-jsx">    <span class="hljs-keyword">const</span> handleAddButtonClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// ...other code</span>
        calculateTotal();
    };

    <span class="hljs-keyword">const</span> handleQuantityIncrease = <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span> {
    <span class="hljs-comment">// ...other code</span>
        calculateTotal();
    };

    <span class="hljs-keyword">const</span> handleQuantityDecrease = <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span> {
    <span class="hljs-comment">// ...other code</span>
        calculateTotal();
    };
</code></pre>
<p>Go ahead and try increasing/decreasing the quantities. You'll notice the total quantity changes as well!</p>
<h2 id="heading-want-more-project-ideas">Want more project ideas?</h2>
<p>Why not try building some React projects to boost your learning even further? </p>
<p>Every week I send out a new project for you to try a working example, starter code, and tips. <a target="_blank" href="https://subscribe.jschris.com">Subscribe to get this straight to your inbox!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Quiz App Using React –with Tips and Starter Code ]]>
                </title>
                <description>
                    <![CDATA[ In this beginner React tutorial we're going to build a quiz app. We'll work with complex state objects, how to handle different state hooks, and render things based on state.  Check it out: Try it yourself If you want to have a go yourself first, he... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-quiz-app-using-react/</link>
                <guid isPermaLink="false">66c8c8e9fe21816c4cb75d19</guid>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Wed, 09 Sep 2020 19:47:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/Build-a-Temperature-control-App--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this beginner React tutorial we're going to build a quiz app. We'll work with complex state objects, how to handle different state hooks, and render things based on state. </p>
<p>Check it out:</p>
<p><img src="https://jschris.com/262a1fab0110d0d612ed69c9bb7c4e7e/project.gif" alt="project" width="600" height="400" loading="lazy"></p>
<h2 id="heading-try-it-yourself">Try it yourself</h2>
<p>If you want to have a go yourself first, here are the scenarios (you can also grab the starter code below):</p>
<ul>
<li>When the user clicks a button, the next question should show</li>
<li>If the user gets the question correct, it should increment their score</li>
<li>When the user gets to the end of the quiz, their total score should be shown</li>
</ul>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/Lya-qYiDqIA" title="Embedded content" loading="lazy"></iframe></div>

<h2 id="heading-starter-code">Starter Code</h2>
<p><a target="_blank" href="https://github.com/chrisblakely01/quiz-app">Grab it over at GitHub here.</a></p>
<h2 id="heading-lets-go">Let's go!</h2>
<p>If you open up the starter code and go to <strong>App.js</strong>, you’ll see I’ve given you a list of questions/answers, stored as an array called <strong>questions</strong>. This is our quiz.</p>
<p>Our first goal is to take the question data from the array, and display it on the screen. </p>
<p>We’ll remove the hardcoded text and take the data from the first question for now, just to get things going. We'll worry about switching questions later.</p>
<p>In our JSX, remove the hardcoded question text and type <code>{questions[0]}</code> to get the first item (or question) in our question array.</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'question-text'</span>&gt;{questions[<span class="hljs-number">0</span>]}&lt;/div&gt;
</code></pre>
<h2 id="heading-rendering-the-question-and-answers">Rendering the Question and Answers</h2>
<p>The first question is an object, so we can use “dot notation” to get access to the properties. Now we’ll just do <code>{question[0].questionText}</code> to get access to the question text for this object:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'question-text'</span>&gt;{questions[<span class="hljs-number">0</span>].questionText}&lt;/div&gt;
</code></pre>
<p>Save and run the app. Notice how the text updates. Remember we're just taking the first question text from the first object in our questions array.</p>
<p>We’ll take a similar approach to the answer options. Remove the hardcoded buttons and we’ll use the map function to loop over the answer options for a given question.</p>
<p>Remember the map function loops over the array and gives us the current item the loop is currently at, in the form of a variable.</p>
<p>Replace the "answer-section" div with the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'answer-section'</span>&gt;
    {questions[<span class="hljs-number">0</span>].answerOptions.map(<span class="hljs-function">(<span class="hljs-params">answerOption, index</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>{answerOption.answerText}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
    ))}
&lt;/div&gt;
</code></pre>
<p>Save and run the app. Notice how four answer buttons appear and the text is rendered dynamically. </p>
<p>Let's recap:</p>
<ul>
<li>We're getting the first question from the questions array: <code>questions[0]</code></li>
<li>The first question is an object, which contains an array of <code>answerOptions</code>. We can get at this array by using dot notation: <code>questions[0].answerOptions</code></li>
<li>Because the <code>answerOptions</code> is an array, we can map over this: <code>questions[0].answerOptions.map</code></li>
<li>Inside the map function, we render a button for each <code>answerOption</code>, and display the text</li>
</ul>
<h2 id="heading-changing-questions-using-state">Changing questions using state</h2>
<p>Now let's go back into our JSX. Notice how if we change <code>questions[0]</code> to <code>questions[1]</code>, or <code>questions[2]</code>, the UI will update. This is because it's taking the data from different questions in our questions array, depending on the index.</p>
<p>What we want to do is use a state object to hold which question the user is currently on, and update this when an answer button is clicked. You can see this from running the code in the final example.</p>
<p>Go ahead and add a state object, which will hold the <strong>current question number</strong> the user is on. This will be initialised to 0 so the quiz takes the first question from the array:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [currentQuestion, setCurrentQuestion] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Now we want to replace the hardcoded '0' in our JSX with this variable. First for the question text:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'question-text'</span>&gt;{questions[currentQuestion].questionText}&lt;/div&gt;
</code></pre>
<p>And also for the question section:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'answer-section'</span>&gt;
    {questions[currentQuestion].answerOptions.map(<span class="hljs-function">(<span class="hljs-params">answerOption, index</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>{answerOption.answerText}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
    ))}
&lt;/div&gt;
</code></pre>
<p>Now if you initialise the <strong>currentQuestion</strong> to something other than 0, for example 1 or 2, the UI will update to show the question and the answers for that particular question. Pretty cool!</p>
<p>Let's add some code so that when we click an answer, we increment the <strong>currentQuestion</strong> value to take us to the next question.</p>
<p>Create a new function called <strong>handleAnswerButtonClick</strong>. This is what will get called when the user clicks an answer. </p>
<p>We’re going to increment the current question value by one, save it to a new variable, and set this new variable into state:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAnswerButtonClick = <span class="hljs-function">(<span class="hljs-params">answerOption</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> nextQuestion = currentQuestion + <span class="hljs-number">1</span>;
    setCurrentQuestion(nextQuestion);
};
</code></pre>
<p>Next add an onClick event to our button like so:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> handleAnswerButtonClick()}&gt;{answerOption.answerText}&lt;/button&gt;
</code></pre>
<p>If we try this, you'll see it works, until we get to the end:</p>
<p><img src="https://jschris.com/static/d0919a4780449b6f825cbf9c88041f24/e46b2/error.webp" alt="error" width="600" height="400" loading="lazy"></p>
<p>So what’s happening? Well in our <strong>handleAnswerButtonClick</strong> function, we’re incrementing the number and setting it to state. Thats OK. </p>
<p>But remember that we use this number to access an array, in order to get the question and answer options. Once we get to 5, it will break as there is no 5th element!</p>
<p>Let’s do a check to make sure we don’t go over the limit. In our handleAnswerButtonClick function let’s add the following condition:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">if</span> (nextQuestion &lt; questions.length) {
    setCurrentQuestion(nextQuestion);
} <span class="hljs-keyword">else</span> {
    alert(<span class="hljs-string">'you reached the end of the quiz'</span>);
}
</code></pre>
<p>This basically says if the next question number is less than the total number of questions, update the state to the next question. Else, we’ve reached the end of the quiz, so show an alert for now.</p>
<h2 id="heading-showing-the-score-screen">Showing the score screen</h2>
<p>Instead of showing an alert, what we want to do is show the “score” screen. </p>
<p>If we look at the JSX, you’ll notice that I’ve put the markup in here for you, we just need to replace “false” with the logic.</p>
<p>So how do we go about this? Well this is a perfect thing to put in state!</p>
<p>Add another state object which will store wether we want to show the score screen or not:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [showScore, setShowScore] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>And replace <code>false</code> with <code>showScore</code> in our JSX:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'app'</span>&gt;{showScore ? <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'score-section'</span>&gt;</span>// ... score section markup<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> : <span class="xml"><span class="hljs-tag">&lt;&gt;</span>// ... quiz question/answer markup<span class="hljs-tag">&lt;/&gt;</span></span>}&lt;/div&gt;
</code></pre>
<p>Nothing will change, but if we change the state value to true, then the score div will show. This is because everything is wrapped in a ternary, meaning:</p>
<blockquote>
<p>“If showScore is true, render the score section markup, else, render the quiz question/answer markup”</p>
</blockquote>
<p>Now, we want to update this state variable when the user has reached the end of the quiz. We have already written the logic for this in our handleAnswerButtonClick function.</p>
<p>All we have to do is replace the alert logic that updates the <strong>showScore</strong> variable to being true:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">if</span> (nextQuestion &lt; questions.length) {
    setCurrentQuestion(nextQuestion);
} <span class="hljs-keyword">else</span> {
    setShowScore(<span class="hljs-literal">true</span>);
}
</code></pre>
<p>If we click through the answers of the quiz, it’ll show the score section when we get to the end. At the moment, the text and score shown is a hardcoded string, so we should make it dynamic.</p>
<h2 id="heading-saving-the-score">Saving the score</h2>
<p>Our next task is to hold a score somewhere in our app, and increment this value if the user selects the correct option.</p>
<p>The logical place to do this is within the “handleAnswerOptonClick” function.</p>
<p>Remember when we iterate over the <strong>answerOptions</strong>, the map function gives us an object for each which includes the <strong>questionText</strong>, and a <strong>boolean value</strong> showing whether that answer is correct or not. This boolean is what we will use to help us increment our score. </p>
<p>In our button, update the function like so:</p>
<pre><code class="lang-jsx">onClick={<span class="hljs-function">()=&gt;</span> handleAnswerButtonClick(answerOption.isCorrect)
</code></pre>
<p>Next update the function to accept this parameter:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAnswerButtonClick = <span class="hljs-function">(<span class="hljs-params">isCorrect</span>) =&gt;</span> {
    <span class="hljs-comment">//... other code</span>
};
</code></pre>
<p>Now we can add some logic here in our function. For now we want to say “if isCorrect is true, we want to show an alert”:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAnswerButtonClick = <span class="hljs-function">(<span class="hljs-params">isCorrect</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (isCorrect) {
        alert(“the answer is correct!”)
    }

    <span class="hljs-comment">//...other code</span>
};
</code></pre>
<p>This is the same as <code>if(isCorrect === true)</code>, just a shorthand version. Now if we try this you will see we get an alert when we click on the correct answer.</p>
<p>Just to recap so far:</p>
<ul>
<li>When we iterate over the buttons, we pass the <code>isCorrect</code> boolean value for that button to the <strong>handleAnswerButtonClick</strong> function</li>
<li>In the function we check if this value is true and show an alert if it is.</li>
</ul>
<p>Next we want to actually save the score. How do you think we do this? If you said state value you are correct!</p>
<p>Go ahead and add another state value called “score”. Remember to prefix the function to change the value with “set” so it’ll be setScore. Initialise it to <code>0</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [score, setScore] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Next instead of showing an alert, we want to update our score by 1 if the user got the answer correct. </p>
<p>In our <strong>handleAnswerButtonClick</strong> function, remove the alert and increment our score by one:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleAnswerButtonClick = <span class="hljs-function">(<span class="hljs-params">isCorrect</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (answerOption.isCorrect) {
        setScore(score + <span class="hljs-number">1</span>);
    }

    <span class="hljs-comment">//...other code</span>
};
</code></pre>
<h2 id="heading-showing-the-score">Showing the score</h2>
<p>To show the score we just have to make a small change to our rendering code. In our JSX, remove the hardcoded string in the score section, and add this new variable:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'score-section'</span>&gt;
    You scored {score} out <span class="hljs-keyword">of</span> {questions.length}
&lt;/div&gt;
</code></pre>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'score-section'</span>&gt;
    You scored {score} out <span class="hljs-keyword">of</span> {questions.length}
&lt;/div&gt;
</code></pre>
<p>Now if we run through the answers, the score is dynamic and will display correctly at the end!</p>
<p>One last thing before we wrap up our quiz app: you’ll notice the current question shown on the UI is always “1”, since it's hardcoded. We need to change this to be more dynamic. </p>
<p>Replace the "question-count" with the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'question-count'</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Question {currentQuestionIndex + 1}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>/{questions.length}
&lt;/div&gt;
</code></pre>
<p>Remember we need the +1 as computers start counting from 0 and not 1.</p>
<h2 id="heading-want-more-project-ideas">Want more project ideas?</h2>
<p>Why not try building some React projects to boost your learning even further? Every week I send out a new project for you to try a working example, starter code, and tips. <a target="_blank" href="https://subscribe.jschris.com">Subscribe to get this straight to your inbox!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Beginner React Project - How to Build Basic Forms Using React Hooks ]]>
                </title>
                <description>
                    <![CDATA[ What we're building In this beginner React Project, we're going to learn how to build basic forms using React hooks. We'll learn how to manage form state, handle validation, and work with submit handlers.  Check it out: Try it yourself If you want t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/beginner-react-project-build-basic-forms-using-react-hooks/</link>
                <guid isPermaLink="false">66c8c8cafe21816c4cb75d10</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Mon, 17 Aug 2020 16:39:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/Basic-Forms-App.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-were-building">What we're building</h2>
<p>In this beginner React Project, we're going to learn how to build basic forms using React hooks. We'll learn how to manage form state, handle validation, and work with submit handlers. </p>
<p>Check it out:</p>
<p><img src="https://jschris.com/0988e0e5975472dc7fe616d48f906494/project.gif" alt="project" width="600" height="400" loading="lazy"></p>
<h2 id="heading-try-it-yourself">Try it yourself</h2>
<p>If you want to have a go yourself first, here are the scenarios (you can also grab the CSS/starter code below):</p>
<ul>
<li>The user should be able to enter values into the form</li>
<li>When the user clicks submit, if any fields are empty, then an error message should appear in red</li>
<li>If the form is submitted and is valid, a success message should appear</li>
</ul>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<p><a target="_blank" href="https://youtu.be/8hU0I8rY4u4">Check out the video walkthrough on YouTube here.</a></p>
<h2 id="heading-starter-code">Starter Code</h2>
<p><a target="_blank" href="https://github.com/chrisblakely01/basic-react-forms">Grab it over at GitHub here.</a></p>
<h2 id="heading-lets-go-adding-state">Let's go! Adding state</h2>
<p>We're going to start by adding a state object to hold our form. We will take a new line at the top of our <code>App function</code> in <strong>App.js</strong> and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [values, setValues] = useState({
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">''</span>,
});
</code></pre>
<p>We have three fields on the form that we need to know the state for.</p>
<p>Now, the initial state is going to be an object. And this object is going to have three values, one for each of these fields. So we'll call them something similar to what they're called in the form.</p>
<p>The <code>firstName</code> is going to be set to blank initially, same with <code>lastName</code> and same with <code>email</code>. </p>
<p>And now, you'll notice an error that says "useState is not defined", so you need to import it from React here. Do this at the top of the file as part of the imports:</p>
<pre><code><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</code></pre><p>Okay, so now it's telling us that these variables aren't used yet. This is fine because we haven't applied these values to the form. But all we've done so far is we've created a state object, and this state object pulls <code>firstName</code>, <code>lastName</code> and <code>email</code>. </p>
<p>Now that we have some values in state, it make sense to apply them to our input fields. Add a <code>value</code> property to each of your input fields like so:</p>
<pre><code class="lang-jsx">
&lt;input
    id=<span class="hljs-string">"first-name"</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"form-field"</span>
    type=<span class="hljs-string">"text"</span>
    placeholder=<span class="hljs-string">"First Name"</span>
    name=<span class="hljs-string">"firstName"</span>
    value={values.firstName}
/&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"last-name"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-field"</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Last Name"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"lastName"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">{values.lastName}</span>
/&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-field"</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">{values.email}</span>
/&gt;</span></span>
</code></pre>
<p>All we've done here is say, "Okay, for this input, the value is going to be whatever value is in state." Let's save this and see what is going on in our forms, to make sure things are still working.</p>
<p>And they're not. Oh, no!</p>
<p>If you select an input and start vigorously typing on the keyboard, nothing appears on the screen. What's going on here?</p>
<h2 id="heading-updating-input-states">Updating input states</h2>
<p>Well, we've said that the value of this input is going to be whatever it is in state. </p>
<p>For example, <code>firstName</code> is currently set to blank because that's what we set it to, but we haven't told the input, "Okay. Any time I type or the input changes, I want you to go and update the state with the new values."</p>
<p>Whenever we do things like this, it effectively gives control to React. So we have to tell React to also update the values. </p>
<p>This means we have to update the state values anytime we type into these fields. </p>
<p>Okay. The simplest way to do this is to create a <strong>handler</strong> for each of these input fields, which updates the state any time an on change event occurs. </p>
<p>Go ahead and add the following just below the state objects:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleFirstNameInputChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.persist();
    setValues(<span class="hljs-function">(<span class="hljs-params">values</span>) =&gt;</span> ({
        ...values,
        <span class="hljs-attr">firstName</span>: event.target.value,
    }));
};
</code></pre>
<p>This takes the event which we get from the <code>onChange</code>. We are basically updating this object and then saving it back to state.</p>
<p>We will copy the old values by doing the three dots, which is also known as a spread operator. And then, we'll just type values and add a comma. </p>
<p>Next, we'll say <strong>firstName is going to be equal to event.target.value</strong>. We want to add this to our input. So in our JSX in the <strong>input for first name</strong>, we'll take a new line somewhere (anywhere, it doesn't really matter), and add the <code>onChange</code> property like so:</p>
<pre><code class="lang-jsx">&lt;input 
    id=<span class="hljs-string">'first-name'</span> 
    <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">'form-field'</span> 
    type=<span class="hljs-string">'text'</span> 
    placeholder=<span class="hljs-string">'First Name'</span> 
    name=<span class="hljs-string">'firstName'</span> 
    value={values.firstName} 
    onChange={handleFirstNameInputChange} /&gt;
</code></pre>
<p>Now, if we go into our browser and start typing, you can see that things work. There rest of them aren't working because we haven't added handlers for these yet. We'll have a look at that in a minute.</p>
<p>Just to recap what's happening: anytime we type into this box, the <strong>onChange event</strong> happens for every keystroke. This gets called every time. </p>
<p>The event gets passed in by React, and we want to update our state object. So to do that, we call the <code>setValues</code> function and pass in a new object with the updated values.</p>
<p>Now, we just want to do the same for <code>lastName</code> and <code>email</code>. Add another handler for each:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleLastNameInputChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.persist();
    setValues(<span class="hljs-function">(<span class="hljs-params">values</span>) =&gt;</span> ({
        ...values,
        <span class="hljs-attr">lastName</span>: event.target.value,
    }));
};

<span class="hljs-keyword">const</span> handleEmailInputChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.persist();
    setValues(<span class="hljs-function">(<span class="hljs-params">values</span>) =&gt;</span> ({
        ...values,
        <span class="hljs-attr">email</span>: event.target.value,
    }));
};
</code></pre>
<p>And don't forget to add the <code>onChange</code> properties to the input fields for each:</p>
<pre><code class="lang-jsx">
&lt;input
    id=<span class="hljs-string">"last-name"</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"form-field"</span>
    type=<span class="hljs-string">"text"</span>
    placeholder=<span class="hljs-string">"Last Name"</span>
    name=<span class="hljs-string">"lastName"</span>
    value={values.lastName}
    onChange={handleLastNameInputChange}
/&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-field"</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">{values.email}</span>
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleEmailInputChange}</span>
/&gt;</span></span>
</code></pre>
<p>Okay. Now is the moment of truth. Is everything working or have we broken something along the way? Let's try it and see. Fill in some data and the input fields should be working now. Hurray!</p>
<p>Even though our input fields are working, we still have a funny issue where if we type stuff in the form and try to submit, it's not going to do anything. It will just refresh the page and all our form data is lost. </p>
<p>Let's do something about that.</p>
<h2 id="heading-showing-a-success-message">Showing a success message</h2>
<p>After clicking register, it should show a success message if the form is valid. What we want to do is go to our JSX, and just beneath the form add a new div. Again, I've added the classes for you for a success message:</p>
<pre><code class="lang-jsx">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">'success-message'</span>&gt;Success! Thank you <span class="hljs-keyword">for</span> registering&lt;/div&gt;
</code></pre>
<p>Now, of course, this isn't going to go anywhere. It's just going to pretend that we've called a server or an end point somewhere. And it's come back with a success message, so we're just going to display this to a user. </p>
<p>But currently it's appearing all the time. What we wanted is only to show this if the user has successfully submitted the form. </p>
<p>So we'll add another state object like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [submitted, setSubmitted] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>We'll keep this separate from the values as it's a different part of the form. We don't want to mix everything up in here and cause an entire re-render. This is going to tell us whether the form has been submitted or not.</p>
<p>It's going to be set to <code>false</code> initially because the first time a user lands on the page, it's not going to be submitted. </p>
<p>And now, we just want to do some clever stuff down in the JSX to say, "If submitted is true, then we want to show the success message." </p>
<p>Update the line we just added with the following:</p>
<pre><code class="lang-jsx">{showSuccess &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">'success-message'</span>&gt;</span>Success! Thank you for registering<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>}
</code></pre>
<p>We'll wrap our <strong>success message</strong> in a ternary operator. That is basically a shorthand if statement that lets us render things dynamically on the page.</p>
<p>The success message will now only appear if <code>showSuccess</code> is true. As you can see now in the browser, this has disappeared. </p>
<p>If we jump back up to our state object for <code>submitted</code> and change this to <code>true</code>, it should appear again. And it does.</p>
<p>We'll change this back to false. And then we'll refresh our Chrome and just see what happens now. </p>
<p>We haven't told the register button or the form what happens on summit, so it's still going to refresh the page. Now, we just need a new handler to handle the register button click. </p>
<p>If we jump into our event handlers and add the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();
    setSubmitted(<span class="hljs-literal">true</span>);
};
</code></pre>
<p><code>event.preventDefault</code> will stop the refresh from happening that we've been seeing. </p>
<p>We'll add some more logic in here in a minute around validation and stuff. But for now, we're just going to say "setSubmitted" to be a true. </p>
<p>Next we need to tell the form to call this function when it gets submitted. Update the JSX to include an <code>onSubmit</code> property in the form tag like so:</p>
<pre><code class="lang-jsx">&lt;form <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">'register-form'</span> onSubmit={handleSubmit}&gt;
    <span class="hljs-comment">//... other code</span>
&lt;/form&gt;
</code></pre>
<p>Now if we run the code in the browser, click the register button, the message appears. Hurray!</p>
<h2 id="heading-adding-validation-and-showing-error-messages">Adding Validation and showing error messages</h2>
<p>Our form is looking good so far, but we're missing one key component of any form, and that is the validation. If we look at our working example, if I submit this with any empty fields, an error appears which says, "Please enter your details."</p>
<p>Below each input, we'll add a <code>&lt;span&gt;</code> which will hold the error message. Your JSX should look similar to this:</p>
<pre><code class="lang-jsx">
&lt;input
    id=<span class="hljs-string">"first-name"</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"form-field"</span>
    type=<span class="hljs-string">"text"</span>
    disabled={showSuccess}
    placeholder=<span class="hljs-string">"First Name"</span>
    name=<span class="hljs-string">"firstName"</span>
    value={values.firstName}
    onChange={handleInputChange}
/&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"first-name-error"</span>&gt;</span>Please enter a first name<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"last-name"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-field"</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Last Name"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"lastName"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">{values.lastName}</span>
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</span>
/&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"last-name-error"</span>&gt;</span>Please enter a last name<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-field"</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">{values.email}</span>
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</span>
/&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email-error"</span>&gt;</span>Please enter an email address<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</code></pre>
<p>You can see these errors always appear, because we haven't got any conditional logic that says "don't appear."</p>
<p>Now, we only want these error messages to show if the register button has been clicked. </p>
<p>We'll jump back into the code. We want to add some conditional logic in and around the error messages, so that they only appear if the button has been clicked and the field is empty:</p>
<pre><code class="lang-jsx">{submitted &amp;&amp; !values.firstName &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">'first-name-error'</span>&gt;</span>Please enter a first name<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>}
</code></pre>
<p>What we're doing here is checking if the form is submitted, and if the <code>firstName</code> state object is empty. If so, we want to display the error message. Again, we're just using a ternary operator, nothing fancy!</p>
<p>Do the same for the other errors:</p>
<pre><code class="lang-jsx">{submitted &amp;&amp; !values.lastName &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">'last-name-error'</span>&gt;</span>Please enter a last name<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>}

<span class="hljs-comment">//...other code</span>

{submitted &amp;&amp; !values.email &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">'email-error'</span>&gt;</span>Please enter an email address<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>}
</code></pre>
<p>If we leave the form blank and click register, errors appear. If we start typing things, we can see that the error disappears. And if we remove what we typed, the error comes back again.</p>
<p>Let's try and submit some stuff. Okay, so this seems to be working. </p>
<p>The last thing we want to do is just make sure that this success message only appears if the form is valid. Go ahead and add a new state value:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [valid, setValid] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>This is used to tell us if our form is valid - remember, using state objects is a good way to hold the "state" of the different parts of your app (who would have guessed?). </p>
<p>The success messages should only appear if submitted is true and followed is also true. Since we've set valid as false initially, it won't show up.</p>
<p>In our <code>handleSubmit</code> function, we want to say value is true if a form is valid. We can do this by checking each of our state values for the form fields, making sure that they are a truthy value. </p>
<p>Add the following:</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> {
event.preventDefault();
<span class="hljs-keyword">if</span>(values.firstName &amp;&amp; values.lastName &amp;&amp; values.email) {
    setValid(<span class="hljs-literal">true</span>);
}
setSubmitted(<span class="hljs-literal">true</span>);
}
</code></pre>
<p>If any of these fields are false, then <code>valid</code> will stay as false. This means the success message div will not get shown. Let's see it working.  If we click register without the fields, our error messages show up. Let's type some valid stuff, hit register, and the message appears! </p>
<h2 id="heading-want-more-project-ideas">Want more project ideas?</h2>
<p>Why not try building some React projects to boost your learning even further? I send out emails every few weeks(ish) with project ideas, starter code, and tips. <a target="_blank" href="https://subscribe.jschris.com">Subscribe to get this straight to your inbox!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Temperature Control App in React – Tips and Starter Code Included ]]>
                </title>
                <description>
                    <![CDATA[ What we're building In this beginner React project, we're going to learn how to use state hooks, handle events, apply CSS based on state, and more! Check it out: Prefer Video Tutorials? Check out the YouTube tutorial here.  Try it yourself If you wa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-beginner-project-tutorial-temperature-control-app/</link>
                <guid isPermaLink="false">66c8c8fa35adc35234e1f4cc</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Fri, 07 Aug 2020 16:15:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/Build-a-Temperature-control-App.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-were-building">What we're building</h2>
<p>In this beginner React project, we're going to learn how to use state hooks, handle events, apply CSS based on state, and more! Check it out:</p>
<p><img src="https://d33wubrfki0l68.cloudfront.net/971e266e2f7f4d42a19477cee7f608cf7b761b4a/e24a5/8363215fb6a3ce3c38580e3ba5fd86bd/project.gif" alt="project" width="320" height="355" loading="lazy"></p>
<h3 id="heading-prefer-video-tutorials">Prefer Video Tutorials?</h3>
<p><a target="_blank" href="https://youtu.be/V3bhcxpoxQU">Check out the YouTube tutorial here.</a> </p>
<h2 id="heading-try-it-yourself">Try it yourself</h2>
<p>If you want to have a go yourself first, here are the scenarios (you can also grab the CSS/starter code below):</p>
<ul>
<li>When the user clicks the "increase button", the temperature should increase</li>
<li>The temperature cannot go above 30</li>
<li>When the user clicks the "decrease button", the temperature should decrease</li>
<li>The temperature cannot go below 0</li>
<li>When the temperature is 15 or above, the background color should change to red (HINT: I've included a style called "hot" you can use)</li>
<li>When the temperature is below 15, the background color should be blue (HINT: I've included a style called "cold" you can use)</li>
</ul>
<h2 id="heading-setupstarter-code">Setup/Starter code</h2>
<p>NOTE: I'm assuming you have a React development environment setup. If not, <a target="_blank" href="https://youtu.be/bZXjHauDNcg">check out this video to help you get started.</a></p>
<p>All we need to get started is to use <strong>create-react-app</strong>. Fire up a terminal and run:</p>
<pre><code class="lang-js">npx create-react-app temperature-control
</code></pre>
<p>Let the terminal do its thing and open up the project in VS Code (or whatever you use).</p>
<p>Next, go into <strong>index.js</strong>, delete everything, and paste in the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

ReactDOM.render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>Go into <strong>index.css</strong>, delete everything, and paste in the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.app-container</span> {
    <span class="hljs-attribute">height</span>: <span class="hljs-number">400px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#2b5870</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">38px</span> <span class="hljs-number">0px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.75</span>);
}

<span class="hljs-selector-class">.temperature-display-container</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">70%</span>;
}

<span class="hljs-selector-class">.temperature-display</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ffffff</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">220px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">220px</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">48px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> <span class="hljs-number">#ffffff</span> solid;
    <span class="hljs-attribute">transition</span>: background <span class="hljs-number">0.5s</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100px</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">80px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">80px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">32px</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ffffff</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">105</span>, <span class="hljs-number">104</span>, <span class="hljs-number">104</span>);
    <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> <span class="hljs-number">#ffffff</span> solid;
}

<span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">184</span>, <span class="hljs-number">184</span>, <span class="hljs-number">184</span>);
    <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:focus</span> {
    <span class="hljs-attribute">outline</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.button-container</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: space-evenly;
    <span class="hljs-attribute">align-items</span>: center;
}

<span class="hljs-selector-class">.neutral</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">184</span>, <span class="hljs-number">184</span>, <span class="hljs-number">184</span>);
}

<span class="hljs-selector-class">.cold</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#035aa6</span>;
}

<span class="hljs-selector-class">.hot</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ff5200</span>;
}
</code></pre>
<p>Lastly, go into <strong>App.js</strong>, delete everything, and paste in the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display'</span>&gt;</span>10°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now we can open a terminal in VS Code and run the following:</p>
<pre><code class="lang-js">npm start
</code></pre>
<p>If all went as planned, you should see the following:</p>
<p><img src="https://d33wubrfki0l68.cloudfront.net/45824af046bb04e327540bada2a1d40195df999a/fba86/static/1001b5afc2ce9716db3d331a43dc2327/f8915/starter.png" alt="starter" width="748" height="944" loading="lazy"></p>
<p>Hurray! This gives us a nice template to play with, without having to worry about any CSS.</p>
<h2 id="heading-make-the-temperature-value-dynamic-using-state">Make the temperature value dynamic - using State</h2>
<p>The first thing we'll do is make the temperature value dynamic. To do this, we'll store the <strong>temperature value in state</strong>. This makes it easier for us to get at the value later, and perform logic using it.</p>
<blockquote>
<p>If something changes on your UI, it's a good idea to put it in state.</p>
</blockquote>
<p>In <strong>App.js</strong> import the <strong>useState</strong> hook at the top of the file like so:</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>;
</code></pre>
<p>Then, add the following within the <strong>App function</strong>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);
</code></pre>
<p>A quick refresher on <strong>useState</strong> - it allows us to hold data in component state. The <strong>useState</strong> hook gives us 2 things:</p>
<ul>
<li>a variable that holds the current state value</li>
<li>a function to change the state value.</li>
</ul>
<p>In this case, we've called our state variable <strong>temperatureValue</strong> and called our function <strong>setTemperatureValue</strong>. We've initialized our temperatureValue to have a value of <strong>10</strong>, by passing the <strong>value 10</strong> to the useState hook.</p>
<p>Now that we have a state value, it's time to use it in our code. Remember, the stuff we get from <strong>useState</strong> can use used just like any old JavaScript variable and function (since that's what they are).</p>
<p>Within our JSX, we want to replace the hardcoded temperature value using our fancy new state variable. Change this line:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'temperature-display'</span>&gt;<span class="hljs-number">10</span>°C&lt;/div&gt;
</code></pre>
<p>So that it becomes this:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'temperature-display'</span>&gt;{temperatureValue}°C&lt;/div&gt;
</code></pre>
<p>Notice how we've used <strong>{}</strong> to render our <strong>temperatureValue</strong> variable. Now, when our temperature value changes, the component will rerender and display the new temperature value. </p>
<p>Our <strong>App.js</strong> file so far looks like this:</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display'</span>&gt;</span>{temperatureValue}°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now if you run the app, and look at the browser, you'll see that things look the same as before. </p>
<p>But if you change the <strong>initial value we pass to the useState hook</strong> from 10 to something else (e.g 15), you'll see that the app updates. This means our state hook is working!</p>
<h2 id="heading-changing-state-on-button-click">Changing state on button click</h2>
<p>Let's work on making the temperature value increase/decrease when the buttons are clicked. </p>
<p>As we know, the useState hook gives us a <strong>setTemperatureValue</strong> function that we can use to change the <strong>temperatureValue</strong>. So, it makes sense for us to wire this up to the button's <strong>onClick</strong> event.</p>
<p>We'll do the increase button first. Replace the increase button with the following:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> setTemperatureValue(temperatureValue + <span class="hljs-number">1</span>)}&gt;+&lt;/button&gt;
</code></pre>
<p>Notice how this calls the <strong>setTemperatureValue</strong> function. We take the current <strong>temperatureValue</strong>, add 1 to it, and pass this as an argument.</p>
<p>So since temperatureValue starts at 10, adding 1 will set the state value to be 11. When the button is clicked again, the state is set to 12, and so on.</p>
<p>Next, we'll do the same with the decrease button. Replace the current decrease button with the following:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> setTemperatureValue(temperatureValue - <span class="hljs-number">1</span>)}&gt;-&lt;/button&gt;
</code></pre>
<p>This is doing the same thing, except we're decreasing the <strong>temperatureValue</strong> this time.</p>
<p>Our code now looks like this:</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display'</span>&gt;</span>{temperatureValue}°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</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> setTemperatureValue(temperatureValue + 1)}&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTemperatureValue(temperatureValue - 1)}&gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Try running this in the browser and clicking the buttons. The values will increase/decrease.</p>
<h2 id="heading-changing-color-based-on-state">Changing color based on state</h2>
<p>Now let's do some fancy stuff. We want the background color of the display to change depending on how high (or low) the temperature is. </p>
<p>If the temperature is 15 degrees or over, we want to change the background color to red. If it's under 15, we want to change the background color to blue. </p>
<p>If you have a look at the CSS, I've provided 2 classes:</p>
<ul>
<li><code>.cold</code> which sets the background to blue</li>
<li><code>.hot</code> which sets the background to red</li>
</ul>
<p>If we add either of these classes to the <strong>temperature display</strong> div, it changes the color. For example:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'temperature-display cold'</span>&gt;{temperatureValue}°C&lt;/div&gt;
</code></pre>
<p>will give the temperature display a blue background, while:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'temperature-display hot'</span>&gt;{temperatureValue}°C&lt;/div&gt;
</code></pre>
<p>will give the temperature display a red background.</p>
<p>Ok, so that's nice and all, but how do we <strong>dynamically</strong> add these classes based on state? </p>
<p>Remember, it's generally a good idea to put the things that can change on your UI into state. So state is a perfect place to hold the current CSS class we want to use.</p>
<p>Let's go ahead and create another state hook to hold the <strong>temperatureColor</strong> like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [temperatureColor, setTemperatureColor] = useState(<span class="hljs-string">'cold'</span>);
</code></pre>
<p>Notice that we initialize our <strong>temperatureColor</strong> state object with a value of "cold" (since our temperature value is initially 10 degrees, we want the background color to be blue).</p>
<p>We can then use <strong>template literals</strong> to dynamically add the classes we want using this state variable. Go ahead and update the code with the following:</p>
<pre><code class="lang-jsx">&lt;div className={<span class="hljs-string">`temperature-display <span class="hljs-subst">${temperatureColor}</span>`</span>}&gt;{temperatureValue}°C&lt;/div&gt;
</code></pre>
<p>This is a tricky syntax to understand, so don't worry if you don't understand straight away. </p>
<p>All this is doing is creating a string and dynamically applying the <strong>temperatureColor</strong> variable. Whenever the <strong>temperatureColor</strong> changes to "hot", the component will rerender and the CSS class "hot" will be added to the className string instead.</p>
<p>Our code so far looks like this:</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);
    <span class="hljs-keyword">const</span> [temperatureColor, setTemperatureColor] = useState(<span class="hljs-string">'cold'</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">temperature-display</span> ${<span class="hljs-attr">temperatureColor</span>}`}&gt;</span>{temperatureValue}°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</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> setTemperatureValue(temperatureValue + 1)}&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTemperatureValue(temperatureValue - 1)}&gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Change the initial <strong>temperatureColor</strong> state variable to "hot" / "cold" and the background of the temperature display should change.</p>
<p>Now that we know this is working, all we have to do is change the state variable. But where do we do this?</p>
<p>Well, we already have an <strong>onClick handler that changes the temperatureValue</strong>, so it makes sense to add our new logic to this handler.</p>
<p>Up until now, we've been using an <strong>inline function</strong> for our click event handlers. And using inline functions is good when we have a one-line function. </p>
<p>But when we have a multi-line function with a bunch of logic, it's best to move the function outside the JSX. This makes our code a bit cleaner.</p>
<p>Go ahead and paste the following just below all the state stuff:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> increaseTemperature = <span class="hljs-function">() =&gt;</span> {
    setTemperatureValue(temperatureValue + <span class="hljs-number">1</span>);
};

<span class="hljs-keyword">const</span> decreaseTemperature = <span class="hljs-function">() =&gt;</span> {
    setTemperatureValue(temperatureValue - <span class="hljs-number">1</span>);
};
</code></pre>
<p>Here we're defining 2 functions - one that increases the temperature and another that decreases the temperature. </p>
<p>Next, we want to change our button's <strong>onClick</strong> properties to call these functions instead of the inline functions we had previously:</p>
<pre><code class="lang-jsx">    &lt;button onClick={increaseTemperature}&gt;+&lt;/button&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{decreaseTemperature}</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>Now, instead of using an inline function, we are <em>passing a reference</em> to our <em>increaseTemperature</em> and <em>decreaseTemperature</em> functions. Our code so far looks like this:</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);
    <span class="hljs-keyword">const</span> [temperatureColor, setTemperatureColor] = useState(<span class="hljs-string">'cold'</span>);

    <span class="hljs-keyword">const</span> increaseTemperature = <span class="hljs-function">() =&gt;</span> {
        setTemperatureValue(temperatureValue + <span class="hljs-number">1</span>);
    };

    <span class="hljs-keyword">const</span> decreaseTemperature = <span class="hljs-function">() =&gt;</span> {
        setTemperatureValue(temperatureValue - <span class="hljs-number">1</span>);
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">temperature-display</span> ${<span class="hljs-attr">temperatureColor</span>}`}&gt;</span>{temperatureValue}°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{increaseTemperature}</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{decreaseTemperature}</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Notice how nothing has changed just yet – we are just <em>refactoring our code</em> and getting ready for upcoming changes. </p>
<p>Now it is much easier to add code logic for either of the button click events - we just write our logic in the appropriate function and life is good.</p>
<p>OK! With refactoring fun out of the way, let's get back to business. So we've said that <strong>When the temperature is 15 degrees or over, we want to change the temperatureColor state value</strong>.</p>
<p>We can add this logic to our <strong>increaseTemperature</strong> function like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> increaseTemperature = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> newTemperature = temperatureValue + <span class="hljs-number">1</span>;
    setTemperatureValue(newTemperature);

    <span class="hljs-keyword">if</span> (newTemperature &gt;= <span class="hljs-number">15</span>) {
        setTemperatureColor(<span class="hljs-string">'hot'</span>);
    }
};
</code></pre>
<p>What have we done?</p>
<ul>
<li>We've created a variable to hold the <strong>newTemperature</strong> value (we did this since we'll be using this variable in a few places)</li>
<li>We set the <strong>temperatureValue</strong>, as we did before</li>
<li>We wrote an <strong>if statement</strong> to check if the <strong>newTemperature</strong> value is more than or equal to, 15</li>
<li>If yes, then we use the <strong>setTemperatureColor</strong> function to set to the <strong>temperatureColor</strong> state value to be "hot"</li>
</ul>
<p>So whenever we click the button enough times that the <strong>temperatureValue</strong> is more than or equal to above 15, the <strong>temperatureColor</strong> variable changes, the component rerenders, and the "hot" class gets added to the temperature display like witchcraft.</p>
<p>But wait! We haven't handled the decrease yet. Which is basically similar to the increase function:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> decreaseTemperature = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> newTemperature = temperatureValue - <span class="hljs-number">1</span>;
    setTemperatureValue(newTemperature);
    <span class="hljs-keyword">if</span> (newTemperature &lt; <span class="hljs-number">15</span>) {
        setTemperatureColor(<span class="hljs-string">'cold'</span>);
    }
};
</code></pre>
<p>This time we subtract one and check if the new value is below 15 before changing the <strong>temperature color</strong></p>
<p>Our final app code looks like this:</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-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [temperatureValue, setTemperatureValue] = useState(<span class="hljs-number">10</span>);
    <span class="hljs-keyword">const</span> [temperatureColor, setTemperatureColor] = useState(<span class="hljs-string">'cold'</span>);

    <span class="hljs-keyword">const</span> increaseTemperature = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> newTemperature = temperatureValue + <span class="hljs-number">1</span>;
        setTemperatureValue(newTemperature);

        <span class="hljs-keyword">if</span> (newTemperature &gt;= <span class="hljs-number">15</span>) {
            setTemperatureColor(<span class="hljs-string">'hot'</span>);
        }
    };

    <span class="hljs-keyword">const</span> decreaseTemperature = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> newTemperature = temperatureValue - <span class="hljs-number">1</span>;
        setTemperatureValue(newTemperature);
        <span class="hljs-keyword">if</span> (newTemperature &lt; <span class="hljs-number">15</span>) {
            setTemperatureColor(<span class="hljs-string">'cold'</span>);
        }
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'app-container'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'temperature-display-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">temperature-display</span> ${<span class="hljs-attr">temperatureColor</span>}`}&gt;</span>{temperatureValue}°C<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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'button-container'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{increaseTemperature}</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{decreaseTemperature}</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Run the app and everything should work - hurray!</p>
<h2 id="heading-a-challenge-to-try">A challenge to try</h2>
<p>You may have noticed that our temperature control isn't very safe - the user can increase the temperature until they reach 100°C, boiling themselves into oblivion, or decrease the temperature until they reach -100°C, turning themselves into a massive ice cube.</p>
<p>The challenge, should you choose to accept it, is to prevent the temperature value from <strong>going over 30°C</strong>, and prevent it from <strong>going under 30°C</strong>.</p>
<p>HINT: The <strong>increaseTemperature</strong> and <strong>decreaseTemperature</strong> functions are perfect places to add this logic!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Hooks for Beginners - A Brain-Friendly Guide on useState and useEffect ]]>
                </title>
                <description>
                    <![CDATA[ "What the heck are hooks?" I found myself asking this just as I thought I had covered all the basis of React. Such is the life of a frontend developer, the game is always changing. Enter Hooks. It's always nice to learn something new right? Of course... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/beginners-guide-to-using-react-hooks/</link>
                <guid isPermaLink="false">66c8c8cd073b3e2196fec387</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Tue, 02 Jun 2020 14:53:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/beginners-guide-to-hooks.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>"What the heck are hooks?"</p>
<p>I found myself asking this just as I thought I had covered all the basis of React. Such is the life of a frontend developer, the game is always changing. Enter Hooks.</p>
<p>It's always nice to learn something new right? Of course! But sometimes we have to ask ourselves "Why? What's the point in this new thing? Do I have to learn it"?</p>
<p>With hooks, the answer is "not right away". If you have been learning React, and have been using class-based components to date, there is no rush to move to hooks. Hooks are optional and can work in tandem with your existing components. Don't you hate it when you have to rewrite your entire codebase to get some new thing to work?</p>
<p>Anyway, here are some reasons why hooks were introduced in the first place and why I recommend beginners should learn them.</p>
<h2 id="heading-using-state-in-functional-components">Using state in functional components</h2>
<p>Before hooks, we could not use state in functional components. That means if you have a nicely crafted and tested functional component that suddenly needs to store state, you are stuck with the painful task of refactoring your functional component into a class component. </p>
<p>Hurray! Allowing state within functional components means we don't have to refactor our presentation components <a target="_blank" href="https://scotch.io/courses/5-essential-react-concepts-to-know-before-learning-redux/presentational-and-container-component-pattern-in-react">Check out this article for more</a>.</p>
<h2 id="heading-class-components-are-clunky">Class components are clunky</h2>
<p>Let's face it, class components come with a lot of boilerplate. Constructors, binding, using "this" everywhere. Using functional components removes a lot of this, so our code becomes easier to follow and maintain.</p>
<p>You can read more about this <a target="_blank" href="https://reactjs.org/docs/hooks-intro.html#classes-confuse-both-people-and-machines">on the React docs:</a></p>
<h2 id="heading-more-readable-code">More readable code</h2>
<p>Since hooks let us use functional components, it means there's less code compared to class components. This makes our code more readable. Well, thats the idea anyway. </p>
<p>We don't have to worry about binding our functions, or remember what "this" relates too, and so on. We can worry about writing our code instead.</p>
<blockquote>
<p><a target="_blank" href="https://www.jschris.com">If you're just starting out with React, I have a bunch of getting started posts on my blog that might help you out! Check it out here:</a></p>
</blockquote>
<h2 id="heading-react-state-hook">React State Hook</h2>
<p>Ah, state. A cornerstone of the React ecosystem. Let's get our feet wet with Hooks by introducing the most common hook that you will be working with - <code>useState()</code>.</p>
<p>Let's take a look at a class component that has state.</p>
<pre><code class="lang-jsx">
<span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./styles.css'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    state = {
        <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.props.initialValue,
    };

    setCount = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count + <span class="hljs-number">1</span> });
    };

    render() {
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is a counter using a class<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{this.state.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">{this.setCount}</span>&gt;</span>Click to 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>With React Hooks, we can rewrite this component and remove a lot of stuff, making it easier to understand:</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">CounterWithHooks</span>(<span class="hljs-params">props</span>) </span>{
    <span class="hljs-keyword">const</span> [count, setCount] = useState(props.initialValue);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is a counter using hooks<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{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;Click to 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> CounterWithHooks;
</code></pre>
<p>On the face of it there is less code, but what's going on?</p>
<h3 id="heading-react-state-syntax">React State Syntax</h3>
<p>So we've seen our first hook! Hurrah!</p>
<pre><code class="lang-jsx"> <span class="hljs-keyword">const</span> [count, setCount] = useState();
</code></pre>
<p>Basically, this uses destructuring assignment for arrays. The <code>useState()</code> function gives us 2 things: </p>
<ul>
<li><strong>a variable to hold the state value</strong>, in this case, it's called <code>count</code> - <strong>a function to change the value</strong>, in this case, it's called <code>setCount</code>.</li>
</ul>
<p>You can name these whatever you want:</p>
<pre><code class="lang-jsx">
<span class="hljs-keyword">const</span> [myCount, setCount] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>And you can use them throughout the code like normal variables/functions:</p>
<pre><code class="lang-jsx">
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CounterWithHooks</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [count, setCount] = useState();

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is a counter using hooks<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{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;Click to Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre>
<p>Notice the <code>useState</code> hook at the top. We're declaring/destructuring 2 things:</p>
<ul>
<li><code>counter</code>: a value which will hold our state value</li>
<li><code>setCounter</code>: a function which will change our <code>counter</code> variable</li>
</ul>
<p>As we continue through the code, you'll see this line:</p>
<pre><code class="lang-jsx">
&lt;h1&gt;{count}&lt;/h1&gt;
</code></pre>
<p>This is an example of how we can use a state hook variable. Within our JSX, we place our <code>count</code> variable within <code>{}</code> to execute it as JavaScript, and in turn the <code>count</code> value gets rendered on the page. </p>
<p>Comparing this to the old "class-based" way of using a state variable:</p>
<pre><code class="lang-jsx">
&lt;h1&gt;{<span class="hljs-built_in">this</span>.state.count}&lt;/h1&gt;
</code></pre>
<p>You'll notice we no longer need to worry about using <code>this</code>, which makes our life a lot easier - for example, the VS Code editor will give us a warning if <code>{count}</code> is not defined, allowing us to catch errors early. Whereas it won't know if <code>{this.state.count}</code> is undefined until the code is run.</p>
<p>On to the next line!</p>
<pre><code class="lang-jsx">
 &lt;button onClick={<span class="hljs-function">() =&gt;</span> setCount(count + <span class="hljs-number">1</span>)}&gt;Click to Increment&lt;/button&gt;
</code></pre>
<p>Here, we're using the <code>setCount</code> function (remember we destructured/declared this from the <code>useState()</code> hook) to change the <code>count</code> variable.</p>
<p>When the button is clicked, we update the <code>count</code> variable by <code>1</code>. Since this is a change of state this triggers a rerender, and React updates the view with the new <code>count</code> value for us. Sweet!</p>
<h3 id="heading-how-can-i-set-the-initial-state">How can I set the initial state?</h3>
<p>You can set the initial state by passing an argument to the <code>useState()</code> syntax. This can be a hardcoded value:</p>
<pre><code class="lang-jsx">
 <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Or can be taken from the props:</p>
<pre><code class="lang-jsx">
 <span class="hljs-keyword">const</span> [count, setCount] = useState(props.initialValue);
</code></pre>
<p>This would set the <code>count</code> value to whatever the <code>props.initialValue</code> is.</p>
<p>That sums up <code>useState()</code>. The beauty of it is that you can use state variables/functions like any other variable/function you would write yourself.</p>
<h3 id="heading-how-do-i-handle-multiple-state-variables">How do I handle multiple state variables?</h3>
<p>This is another cool thing about hooks. We can have as many as we like in a component:</p>
<pre><code class="lang-jsx">
 <span class="hljs-keyword">const</span> [count, setCount] = useState(props.initialValue);
 <span class="hljs-keyword">const</span> [title, setTitle] = useState(<span class="hljs-string">"This is my title"</span>);
 <span class="hljs-keyword">const</span> [age, setAge] = useState(<span class="hljs-number">25</span>);
</code></pre>
<p>As you can see, we have 3 seperate state objects. If we wanted to update the age for example, we just call the <strong>setAge()</strong> function. The same with <strong>count</strong> and <strong>title</strong>. We no longer are tied to the old clunky class component way where we have one massive state object stored using <strong>setState()</strong>:</p>
<pre><code class="lang-jsx">
<span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: props.initialValue, <span class="hljs-attr">title</span>: <span class="hljs-string">"This is my title"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> })
</code></pre>
<h2 id="heading-so-what-about-updating-things-when-props-or-state-changes">So, what about updating things when props or state changes?</h2>
<p>When using hooks and functional components, we no longer have access to React lifecycle methods like <code>componentDidMount</code>, <code>componentDidUpdate</code>, and so on. Oh, dear! Do not panic my friend, React has given us another hook we can use:</p>
<ul>
<li><em>Drum Roll</em> * </li>
</ul>
<h2 id="heading-enter-useeffect">Enter useEffect!</h2>
<p>The Effect hook (<strong>useEffect()</strong>) is where we put "side effects".</p>
<p>Eh, side effects? What? Let's go off-track for a minute and discuss what a side effect actually is. This will help us understand what <code>useEffect()</code> does, and why it's useful.</p>
<p>A boring computer-y explanation would be.</p>
<blockquote>
<p>"In programming, a side effect is when a procedure changes a variable from outside its scope"</p>
</blockquote>
<p>In React-y terms, this means "when a component's variables or state changes based on some outside thing". For example, this could be:</p>
<ul>
<li>When a component receives new props that change its state</li>
<li>When a component makes an API call and does something with the response (e.g, changes the state)</li>
</ul>
<p>So why is it called a side effect? Well, <em>we cannot be sure what the result of the action will be</em>. We can never be 100% certain what props we are going to receive, or what the response from an API call would be. And, we cannot be sure how this will affect our component. </p>
<p>Sure we can write code to validate, and handle errors, and so on, but ultimately we cannot be sure what the side effects of said things are. </p>
<p>So for example, when we change state, based on some <em>outside thing</em> this is know as a side effect.</p>
<p>With that out of the way, let's get back to React and the useEffect Hook!</p>
<p>When using functional components we no longer have access to life cycle methods like <code>componentDidMount()</code>, <code>componentDidUpdate()</code> etc. So, in effect (pun intended), the useEffect hooks replace the current React Life Cycle hooks.</p>
<p>Let's compare a class-based component with how we use the useEffect hook:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    componentDidMount() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'I have just mounted!'</span>);
    }

    render() {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Insert JSX here<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
    }
}
</code></pre>
<p>And now using useEffect():</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'I have just mounted!'</span>);
    });

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Insert JSX here<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}
</code></pre>
<p>Before we continue, it's important to know that, by default, <strong>the useEffect hook runs on every render and re-render</strong>. So whenever the state changes in your component or your component receives new props, it will rerender and cause the useEffect hook to run again.</p>
<h3 id="heading-running-an-effect-once-componentdidmount">Running an effect once (componentDidMount)</h3>
<p>So, if hooks run every time a component renders, how do we ensure a hook only runs once when the component mounts? For example, if a component fetches data from an API, we don't want this happening every time the component re-renders!</p>
<p>The <code>useEffect()</code> hook takes a second parameter, an array, <strong>containing the list of things that will cause the useEffect hook to run</strong>. When changed, it will trigger the effect hook. The key to running an effect once is to pass in an empty array:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'This only runs once'</span>);
}, []);
</code></pre>
<p>So this means the useEffect hook will run on the first render as normal. However, when your component rerenders, the useEffect will think "well, I've already run, there's nothing in the array, so I won't have to run again. Back to sleep for me!" and simply does nothing.</p>
<blockquote>
<p>In summary, empty array = <code>useEffect</code> hook runs once on mount</p>
</blockquote>
<h3 id="heading-using-effects-when-things-change-componentdidupdate">Using effects when things change (componentDidUpdate)</h3>
<p>We've covered how to make sure a <code>useEffect</code> hook only runs once, but what about when our component receives a new prop? Or we want to run some code when the state changes? Hooks let us do this as well!</p>
<pre><code class="lang-jsx"> useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"The name props has changed!"</span>)
 }, [props.name]);
</code></pre>
<p>Notice how we are passing stuff to the useEffect array this time, namely <em>props.name</em>. </p>
<p>In this scenario, the useEffect hook will run on the first load as always. Whenever your component receives a new <strong>name prop</strong> from its parent, the useEffect hook will be triggered, and the code within it will run.</p>
<p>We can do the same thing with state variables:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">"Chris"</span>);

 useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"The name state variable has changed!"</span>);
 }, [name]);
</code></pre>
<p>Whenever the <code>name</code> variable changes, the component rerenders and the useEffect hook will run and output the message. Since this is an array, we can add multiple things to it:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">"Chris"</span>);

 useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Something has changed!"</span>);
 }, [name, props.name]);
</code></pre>
<p>This time, when the <code>name</code> state variable changes, or the <code>name prop</code> changes, the useEffect hook will run and display the console message.</p>
<h3 id="heading-can-we-use-componentwillunmount">Can we use componentWillUnmount()?</h3>
<p>To run a hook as the component is about to unmount, we just have to return a function from the <code>useEffect</code> hook:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running effect'</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'unmounting'</span>);
    };
});
</code></pre>
<h2 id="heading-can-i-use-different-hooks-together">Can I use different hooks together?</h2>
<p>Yes! You can use as many hooks as you want in a component, and mix and match as you like:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span> = (<span class="hljs-params"></span>) =&gt; </span>{
    <span class="hljs-keyword">const</span> [name, setName] = useState();
    <span class="hljs-keyword">const</span> [age, setAge] = useState();

    useEffect(<span class="hljs-function">()=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"component has changed"</span>);
    }, [name, age])

    <span class="hljs-keyword">return</span>(
        &lt;div&gt;Some jsx here...&lt;div&gt;
    )
}
</code></pre>
<h2 id="heading-conclusion-what-next">Conclusion - What Next?</h2>
<p>There you have it. Hooks allow us to use good old fashioned JavaScript functions to create simplier React components, and reduce alot of boilerplate code. </p>
<p>Now, run off into the world of Reac hooks and try building stuff yourself! Speaking of building stuff yourself...</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get Started with React — A Modern Project-based Guide for Beginners (Including Hooks) ]]>
                </title>
                <description>
                    <![CDATA[ So you want to start learning React, eh? Then you've come to the right place. This guide will walk you through everything you need to know when getting started with React.  We'll get set up, explain the "hows and whys" behind the basic concepts, and ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/getting-started-with-react-a-modern-project-based-guide-for-beginners-including-hooks-2/</link>
                <guid isPermaLink="false">66c8c8dbe9e57963a5d82ac2</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Sat, 16 May 2020 13:18:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/getting-started-with-react.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>So you want to start learning React, eh? Then you've come to the right place. This guide will walk you through everything you need to know when getting started with React. </p>
<p>We'll get set up, explain the "hows and whys" behind the basic concepts, and build a small project which pulls data from an API so we can see everything in action.</p>
<p>This will be a long one, so skip/re-read sections as you need using the "Jump to Section" links below. With that out of the way, grab a drink, buckle up, and let's get started.</p>
<h4 id="heading-prefer-video-tutorials">Prefer Video Tutorials?</h4>
<p>You can check out the <a target="_blank" href="https://youtu.be/bZXjHauDNcg">YouTube tutorial for this article here.</a></p>
<h2 id="heading-jump-to-section">Jump to Section</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a><ul>
<li><a class="post-section-overview" href="#heading-basic-javascript">Basic JavaScript</a></li>
<li><a class="post-section-overview" href="#heading-basic-html">Basic HTML</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-development-environment">Development Environment</a><ul>
<li><a class="post-section-overview" href="#heading-nodejs">Node.js</a></li>
<li><a class="post-section-overview" href="#heading-visual-studio-code">VS Code</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-creating-a-react-app">Creating a React App</a></li>
<li><a class="post-section-overview" href="#heading-exploring-create-react-app">Exploring Create React App</a><ul>
<li><a class="post-section-overview" href="#heading-node-modules">Node Modules</a></li>
<li><a class="post-section-overview" href="#heading-public-folder">Public Folder</a></li>
<li><a class="post-section-overview" href="#heading-indexhtml">Index.html</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-our-first-component">Our First Component</a></li>
<li><a class="post-section-overview" href="#heading-jsx">JSX</a><ul>
<li><a class="post-section-overview" href="#heading-making-things-dynamic">Making Things Dynamic</a></li>
<li><a class="post-section-overview" href="#heading-handling-events">Handling Events</a></li>
<li><a class="post-section-overview" href="#heading-calling-functions">Calling Functions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-a-component-gets-rendered">How a Component gets Rendered</a></li>
<li><a class="post-section-overview" href="#heading-lets-build-a-contacts-list">Lets Build a Contacts List!</a><ul>
<li><a class="post-section-overview" href="#heading-get-the-styles">Get the Styles</a></li>
<li><a class="post-section-overview" href="#heading-creating-the-contact-card">Creating the Contact Card</a></li>
<li><a class="post-section-overview" href="#makingourcontact-card-reusable">Making Our Contact Card Reusable</a></li>
<li><a class="post-section-overview" href="#heading-lets-talk-about-state-the-usestate-hook">Lets talk about State</a></li>
<li><a class="post-section-overview" href="#heading-updating-state">Updating State</a></li>
<li><a class="post-section-overview" href="#heading-introducing-props">Introducing Props</a></li>
<li><a class="post-section-overview" href="#heading-using-props-within-a-component">Using Props within a component</a></li>
<li><a class="post-section-overview" href="#heading-rendering-components-from-a-list">Rendering components from a List</a></li>
<li><a class="post-section-overview" href="#heading-pulling-data-from-an-api">Pulling data from an API</a></li>
<li><a class="post-section-overview" href="#heading-introducing-useeffect">Introducing useEffect</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You don't need to know any React before reading this guide. But there are a few things you will need to be familiar with if you want to get the most out of this React guide:</p>
<h3 id="heading-basic-javascript">Basic JavaScript</h3>
<p>React is a JavaScript library, so it makes sense to know JavaScript before learning React, right? Don't worry, you won't need to know JavaScript inside out — you only need to know the basics:</p>
<ul>
<li>Variables, functions, data types</li>
<li>Arrays and Objects</li>
<li>ES6 Syntax (using let &amp; const, Arrow Functions, Destructuring Assignment, classes, importing/exporting, etc)</li>
<li>How JavaScript is used to manipulate the DOM </li>
</ul>
<h3 id="heading-basic-html">Basic HTML</h3>
<p>In React, we use what's called <strong>JSX</strong> to create the HTML for our webpages. We'll explain JSX in depth later, but for now make sure you have a good foundation when it comes to HTML:</p>
<ul>
<li>How to structure HTML (how to nest elements and so on)</li>
<li>HTML attributes (like "id", "class", "onclick" and so on)</li>
</ul>
<blockquote>
<p> <a target="_blank" href="https://subscribe.jschris.com">Need some JavaScript review? Subscribe to get my latest book "React-Ready JavaScript" which will help you get ramped up on the JavaScript you need before getting started with React!</a></p>
</blockquote>
<h2 id="heading-development-environment">Development Environment</h2>
<p>The first thing we're going to do is set up a development environment. If you've already setup <strong>Node.js</strong> and installed <strong>Visual Studio Code</strong> (or your preferred IDE), you can go ahead and skip to the next section.</p>
<h3 id="heading-nodejs">Node.js</h3>
<p><a target="_blank" href="https://nodejs.org/en/download/">Go here and download</a> the right package for your OS (Mac/windows etc)</p>
<p>When the installation completes, open a terminal  and type this command: </p>
<pre><code class="lang-js">node -v
</code></pre>
<p>This should show output the version of Node you just installed:</p>
<p><img src="https://jschris.com/static/75f85dfa0c07e6b38092fb8eb832a189/b5cea/node.png" alt="node" width="600" height="400" loading="lazy"></p>
<p>This means that the <code>node</code> command works and node has installed successfully — hurray! If you see any errors, try reinstalling Node from the package you downloaded and retry the command again.</p>
<h3 id="heading-visual-studio-code">Visual Studio Code</h3>
<p>Visual Studio Code is a popular open-source IDE that works well for frontend development. There are a bunch of others you can try — see what your favourite is and download that if you prefer. For now, we'll run with VS Code.</p>
<p><a target="_blank" href="https://code.visualstudio.com/download">Click here and download</a> the version for your platform: </p>
<p>Follow the installation steps, and you should be good to go. Go ahead and fire up Visual Studio Code.</p>
<p>That's enough development setup for now. There are other nice things you can install (VS Code extensions etc) but we don't need those right now —We're here to learn React!</p>
<h2 id="heading-creating-a-react-app">Creating a React App</h2>
<p>The next step is to create a React project. Lucky for us, the fine folk at Facebook have made this really simple. All we have to do is run a command within our terminal:</p>
<pre><code class="lang-jsx">npx create-react-app my-app
</code></pre>
<p>This creates a project for us called "my-app" and sets everything up automatically. Pretty cool.</p>
<p>Go ahead and open up a terminal in the directory you want to create your app, e.g. a "projects" folder, and run the command. Let the terminal do its thing, and after a while, this will complete and show you some commands:</p>
<p><img src="https://jschris.com/static/9d651a0597f10abac0a8687011b437f1/78363/cra-install.png" alt="cra-install" width="600" height="400" loading="lazy"></p>
<p>Notice the <strong>create-react-app</strong> output has told us what we need to do to start the app. Go ahead and run the commands in your terminal:</p>
<pre><code>cd my-app
yarn start
</code></pre><p>This will start a development server and open up a web browser for you:</p>
<p><img src="https://jschris.com/static/a1a4aeb3c265e6753ce67bb5e9c66fe0/cb922/cra-start.png" alt="cra-start" width="600" height="400" loading="lazy"></p>
<p>You've just set up your first React App! If you want to learn more about what's going on, (check out the "create-react-app" GitHub:)[https://github.com/facebook/create-react-app]</p>
<h2 id="heading-exploring-create-react-app">Exploring Create React App</h2>
<p>Open up Visual Studio code (or whatever IDE you installed) and select <strong>File &gt; Open…</strong> and select the <strong>my-app</strong> folder that was just created for us using <em>create-react-app</em>. This will open up our shiny new react app in the IDE, so we can write some code! </p>
<p>You should see the project structure to the right:</p>
<p><img src="https://jschris.com/static/64e7647ba04867a1c923bd3d1bac51d9/fdaf8/project-tree.png" alt="project-tree" width="600" height="400" loading="lazy"></p>
<p>Look at all that stuff! Don’t worry too much about a lot of it, it’s mostly boilerplate code and config that we won’t be touching too much in this tutorial — phew! However since you’re a curious developer, let’s have a look at the <strong>project tree</strong> and see what we have:</p>
<h3 id="heading-node-modules">Node Modules</h3>
<p>This is where our packages go that we install through NPM (Node Package Manager). If you’re not familiar with NPM, it’s a glorious place where we can share code (usually open source) that other developers can use instead of writing their own. </p>
<p>Instead of using <strong>script tags</strong> like we do in traditional HTML, we install these modules as part of the application. Then, we use an <strong>import statement</strong> to access the code from that module. We’ll see this in action later.</p>
<h3 id="heading-public-folder">Public Folder</h3>
<p>This is where our bundled code goes. When we are ready to deploy our app, we run a <strong> build script</strong>and the final files go in here. This will typically be our HTML, JavaScript, and CSS files. This is the folder we dump onto a web server somewhere, so that we can let users see our app via a URL</p>
<h3 id="heading-indexhtml">Index.html</h3>
<p>The <strong>index.html</strong> is the entry point, or the first thing the web browser loads when a user navigates to the URL hosting our app. </p>
<p>If we look at the file, it’s a just a normal HTML file with normal HTML stuff that you will hopefully be familiar with. If we look at the body — it’s empty. React will dynamically convert our React code into HTML and load it here, in the “root” div.</p>
<p>With that out of the way, let’s look at the juicy parts — the code.</p>
<h2 id="heading-our-first-component">Our First Component</h2>
<p>Open up <strong>App.js</strong> from the project tree. This is the Main component in our application. This is the first component to get rendered. It’s the “big cheese” of components.</p>
<p>The first thing we’re going to do in our big cheese component is delete everything, and build our very own component from scratch, to better understand what’s going on.</p>
<p>Now that we have a nice blank slate to play with we will start by importing <strong>react</strong>. This brings the React library into <em>scope</em> and gives us access to all the lovely features:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</code></pre>
<p>Next we will declare a function. We’ll use ES6 arrow functions here. That’s more or less what a “component” is — a function with some logic and markup. We’re also going to export this function so we can use it elsewhere:</p>
<pre><code class="lang-JSX"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Within our function we want to write <code>return()</code>. This is what get’s <em>returned</em> from this component, and contains our markup which gets converted and rendered as HTML. </p>
<p>Finally let’s add a <code>&lt;div&gt;</code> with a <code>&lt;h1&gt;</code> title tag. Our finished component looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>
             This is our first React App - isn't it marvellous?!
       <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now you’re probably thinking, "Woah! HTML in a function? What is this madness?" Even though it looks like HTML, it’s actually something called <strong>JSX (JavaScript XML)</strong>. This basically allows us to mix JavaScript and HTML together.</p>
<p>This might seem a bit strange. We originally learned front end development by separating our HTML and JavaScript (and even CSS). Yet JavaScript and the way we design apps has evolved, and keeping everything together in the same “component” makes it easier to maintain and reuse our code.</p>
<p>Let’s see this in action. Open your terminal and run</p>
<pre><code>npm start
</code></pre><p>This should open the browser and you should see the app running.</p>
<p>Congrats! You’ve just created your first component!</p>
<h2 id="heading-jsx">JSX</h2>
<p>You probably have some question marks floating above your head when thinking about this JSX thing. Let’s take a deeper look into this.</p>
<pre><code class="lang-jsx">  <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>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>
          This is our first React App - isn't it marvellous?!
      <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
</code></pre>
<p>This looks like HTML, but it’s not. This is <strong>JSX</strong>! Even though it looks like normal HTML, what’s happening behind the scenes is that React is <strong>creating the element tree</strong>, using this syntax:</p>
<pre><code class="lang-jsx">React.createElement(component, props, ...children)
</code></pre>
<ul>
<li>component: The <strong>HTML element</strong> you wish to created, i.e. <code>h1</code>, <code>div</code> etc</li>
<li>props: any <code>props</code> you wish to pass to that component (we’ll talk about props later)</li>
<li>children: An <strong>array of HTML elements</strong> that are nested within this element</li>
</ul>
<p>So, the same component we have just created can be written as so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    React.createElement(
      <span class="hljs-string">"div"</span>,
      <span class="hljs-literal">null</span>,
      React.createElement(<span class="hljs-string">"h1"</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">"Hello React World"</span>),
      React.createElement(
        <span class="hljs-string">"h2"</span>,
        <span class="hljs-literal">null</span>,
        <span class="hljs-string">"This is our first React App - isn't it marvellous?!"</span>
      )
    )
  );
}
</code></pre>
<p>Which looks a bit nasty (it was even nastier trying to type it out). If you trace through it carefully, you can see we are creating a <code>div</code> element, which has no props (indicated by passing <code>null</code> as a second argument). Lastly we are creating 2 more elements using the <code>createElement</code> syntax — our <code>H1</code> and our <code>H2</code> elements.</p>
<p>If you’ve been playing with JavaScript for a while, you might have noticed that this is similar to <code>document.createElement</code>.  And it is! This is a JavaScript library after all! </p>
<p>This is the advantage of JSX in React — it lets us write HTML like syntax, without the messy <code>React.createElement()</code> stuff.</p>
<p>In the real world, React developers almost exclusively use JSX to write their code. No, this section wasn’t a waste of time — it’s always good to understand what happens under the hood. Knowledge is power (and less questions in my inbox)!</p>
<p>###Making things dynamic</p>
<p>So we’ve seen JSX, and gotten over our fear of it (hopefully). But what’s the point? Why use this JSX thing, when we could just use HTML? They look the same? Right?</p>
<p>Good question my friend! Well, if we remember what JSX stands for — JavaScript XML. This means we can use JavaScript to make things dynamic. Our previous example looks like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is our first React App - isn't it marvellous?!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now let’s say we want to make our text more dynamic. Firstly let’s add a variable to hold our message:</p>
<p><code>cont message = "This is my first variable rendered in JSX!"</code></p>
<p>Now to add JavaScript to this, we use <strong> curly braces</strong>: </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> message = <span class="hljs-string">"This is my first variable rendered in JSX!"</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>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{message}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>If you run this in the browser, you’ll notice the text of our message variable appears. Go ahead and change the message variable text to something else and watch the magic happen. </p>
<p>We use <strong>curly braces</strong> to tell the compiler “<strong><em>execute this code as JavaScript</em></strong>”. If we didn’t have curly braces, the <strong>message</strong> variable wouldn't get executed as JavaScript and instead, the text “message” would appear on the screen. Try this out and see! </p>
<h3 id="heading-handling-events">Handling Events</h3>
<p>The same approach can be taken when with handling events. When using JSX, React gives us access to <strong>event listeners</strong>  you may already be familiar with: <strong>onClick</strong>, <strong>onPress</strong>, <strong>onSubmit</strong> and so on. </p>
<p>Let’s say we want to display an alert when the message is clicked. Firstly, we add the <strong>onClick</strong> property to our <strong>h2</strong> tag. </p>
<p>The <strong>onClick</strong> property accepts a function (in other words, we pass a function as an argument. This function will call the alert like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> message = <span class="hljs-string">"This is my first variable rendered in JSX!"</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>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=&gt;</span> alert("you clicked the message!")}&gt;{message}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Notice how we use a <strong>arrow</strong> function here to create a nice, concise inline function. If you’re not familiar with this syntax, make sure to <a target="_blank" href="https://subscribe.jschris.com">checkout my book where I cover this and more here</a>.</p>
<p>Again, notice how we have put this code within <strong>curly braces</strong>, to ensure the function gets executed as JavaScript.</p>
<h3 id="heading-calling-functions">Calling functions</h3>
<p>So we looked at inline functions in the last example. Since JSX is JavaScript, we can create and reference functions <strong>outside of the return block</strong>. Our last example could look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> message = <span class="hljs-string">"This is my first variable rendered in JSX!"</span>;  

  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span>{
    alert(<span class="hljs-string">"you clicked the message!"</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>Hello React World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>{message}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Notice how we created a function called <strong>handleClick</strong> which alerts the message. Instead of using an inline function, we reference this function in our <strong>onClick</strong> property. Try this out and see what happens.</p>
<p>These are just some examples as to how we can use JavaScript to make things dynamic, and hopefully shows you the power of JSX. We’ll deepen our understandings later as we build out an example, so don't worry if some things don’t make sense just yet!</p>
<h2 id="heading-how-a-component-gets-rendered">How a Component gets Rendered</h2>
<p>Hopefully I’ve cleared up some of the questions you might have around JSX. The next thing you might be wondering is — how does a component get rendered? Where? When? </p>
<p>Let’s start at the beginning. If you look back to our file structure we have an <strong>index.js</strong> file. This is the first file to run (we often call this an “Entry Point”). This is typically by convention — you can change the entry point if you want, but for now we’ll leave it alone. </p>
<p>If we dig into the file, you’ll notice we have this line:</p>
<pre><code class="lang-jsx">ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
</code></pre>
<p>Notice we have <code>document.getElementById(“root”)</code> — finally some normal looking JavaScript! This gets the <strong>root</strong> element from the DOM using plain ol’ JavaScript, and renders our App Component within it. Our App component is imported like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>
</code></pre>
<p>Remember we <em>exported</em> our app component in App.js. This lets other files/components import and use our App component.</p>
<p>So where does the <strong>root</strong> element come from? Well, remember our <em>index.html</em> file in the public folder? This index.html file is the first HTML file to get loaded when the website loads </p>
<p>Within it we have a <code>div</code> with an ID of <code>root</code>, which is empty. This is where React loads our components. Let’s have a look at this in the dev tools.</p>
<p>Open up Chrome (or whatever browser you use) and inspect the dev tools. You’ll see somewhere in the tree a <strong>div with id=“root”</strong>, as well as the <strong>HTML rendered from our App component</strong>. Pretty cool!</p>
<p><img src="https://jschris.com/static/48936a3669e8feaa26c72f9908400f73/fbdcb/id-root-dev-tools.png" alt="id-root-dev-tools" width="600" height="400" loading="lazy"></p>
<h2 id="heading-quick-summary">Quick Summary</h2>
<p>Before moving on, let’s quickly summarise what we’ve learned so far:</p>
<ul>
<li>We have an <em>index.html</em> file, which is the skeleton of our web app</li>
<li>When the app starts, <em>index.html</em> loads, and imports our App Component</li>
<li>The JSX in the App component get’s converted to HTML, which is then rendered in the <strong>index.html file at the root div</strong></li>
</ul>
<h2 id="heading-lets-build-a-contacts-list">Lets Build a Contacts List!</h2>
<p>Now that we have our feet wet with React, and have a better understanding of how things fit together, let’s build an example application using what we have learned so far. We’ll also learn some common React features that will help you well on to the road to getting started with React. Let’s go!</p>
<p>Our contacts list will display a number of a contacts, including their name, email, age and avatar (or, profile image). 
We’ll build this up gradually, eventually pulling data from an API. How exciting! </p>
<p><img src="https://jschris.com/static/093da2b0c6947b52d83b42183d172718/6569d/contacts-list-intro.png" alt="contacts-list-intro" width="600" height="400" loading="lazy"></p>
<h2 id="heading-get-the-styles">Get the styles</h2>
<p>Since this is a React tutorial, we’re going to focus on the inner workings of React and not worry about creating nice styles. In your source folder, create a new file <code>styles.css</code> and paste in the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.contact-card</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#ffffff</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">42</span>, <span class="hljs-number">84</span>, <span class="hljs-number">104</span>);
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Segoe UI"</span>, Tahoma, Geneva, Verdana, sans-serif;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">25px</span> -<span class="hljs-number">16px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.75</span>);
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">max-height</span>: <span class="hljs-number">125px</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.contact-card</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<p>Next, go into <strong>App.js</strong> and import the stylesheet like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;
</code></pre>
<h2 id="heading-creating-the-contact-card">Creating the Contact Card</h2>
<p>While we’re still in <strong>App.js</strong>,  let’s add the basic JSX to get our layout for the contact card in place. Remove everything from the <strong>return</strong> statement and add the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"contact-card"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<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>
&lt;/div&gt;
</code></pre>
<p>All we’re doing here is creating a <strong>div</strong> to “wrap” the contact card details, adding an image (the image will use a placeholder taken from the web for now), and adding a few <strong>p</strong> tags to hold the details we need in the contact card. Finally we’re adding some <strong>CSS classes</strong> taken from <code>styles.css</code>;</p>
<blockquote>
<p>NOTE: to reference CSS classes, we need to use the <strong>className</strong> keyword. This is because we are writing JSX, and “class” is a reserved word in JavaScript.</p>
</blockquote>
<p>Here’s what we have so far in our <strong>App.js</strong> file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>If you run this in the browser, you should see something similar to the following:</p>
<p><img src="https://jschris.com/static/adff13952d09891bcb6c1d1c7a694bb9/89048/contac-card-template.png" alt="contac-card-template" width="600" height="400" loading="lazy"></p>
<h2 id="heading-making-our-contact-card-reusable">Making our Contact Card Reusable</h2>
<p>OK so we have our contact card! However it’s not very reusable. We know that we are going to need to <strong>reuse this code</strong> if we want to render more than one card, so it makes sense to break this out <strong>into it’s own component</strong></p>
<blockquote>
<p>NOTE — To make it easier to follow, I am going to a put all the components we make into <strong>App.js</strong> . In the real world it would be better to split these different components into their own files, and import/export them where appropriate.</p>
</blockquote>
<p>Just beneath the <strong>App</strong> function, create a new function called <strong>ContactCard</strong>, and copy the JSX from <strong>App</strong> to  <strong>ContactCard</strong> like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Again, a component in React is just a <strong>function that returns some JSX</strong>.  Now that we’ve moved our JSX to the <strong>ContactCard</strong> we can use this component within our main <strong>App component</strong>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>We use our own components like any old HTML/JSX tag. We just put the <strong>name of our component in angle brackets.</strong> Our <strong>App.js</strong> file should look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

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

<span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Now if you run this in the browser, things will look the same as they did before — which is what we want. We now have a <strong>ContactCard</strong> component that we can use as many times as we like:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>Update the <strong>App</strong> component to include another 2 <strong>ContactCard</strong> components. The above example will render 3 contact cards in the browser. Go and check it out!</p>
<blockquote>
<p>Think of this like a “stamp” on the page. Every <strong>ContactCard</strong> component we add is another “stamp” and renders the same markup on the page</p>
</blockquote>
<h2 id="heading-lets-talk-about-state-the-usestate-hook">Let’s talk about State — the useState Hook</h2>
<p>If you’ve been getting started with React already, you may have heard of the term <strong>state</strong>. State is quite a big deal in React. So what is it?</p>
<blockquote>
<p>State is basically an object that represents a part of an app that can change, which the UI “reacts” to. State can be anything; objects, booleans, arrays, strings or integers </p>
</blockquote>
<p>Let’s take an example.</p>
<p>Some people who appear in our contact list are shy and do not want their age being displayed until a button is clicked. We can store <strong>whether the age should be shown or not</strong> in state by using the <strong>useState hook within the component</strong>. Which looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [showAge, setShowAge] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>“What the hell is going on here?” Let me explain.</p>
<p>The <strong>useState object</strong> gives us a variable with the <strong>current value</strong>, and a function that <strong>lets us change that value</strong>. When we call <strong>useState</strong> we can define an <strong>initial</strong>value (in this case, <strong>false</strong>).</p>
<p>We use <strong>destructuring assignment</strong> on the <strong>useState hook</strong> to get these. You don’t have to worry about destructuring assignment right now, just remember that the first variable lets us access the state value, the second one lets us change it.</p>
<p>Go ahead and add the above code snippet to the <strong>ContactCard</strong> component like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [showAge, setShowAge] = 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">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Now we have a state object, how do we use it? Well, we can reference the <code>showAge</code> variable like any other variable. In this case, we want to _only show the age if the <code>showAge</code> variable is <code>true</code>. </p>
<p>We can do this using the <em>ternary operator</em> :</p>
<pre><code class="lang-jsx">{showAge === <span class="hljs-literal">true</span> ? <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span> : <span class="hljs-literal">null</span>}
</code></pre>
<p>This example reads as <em>if the showAge variable is true, render the age, if not, render nothing</em>.</p>
<p>Go ahead and add this to the <strong>ContactCard</strong> component, like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [showAge, setShowAge] = 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">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: Jenny Han<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: Jenny.Han@notreal.com<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {showAge === true ? <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> : null}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Now, if you run the app in the browser, you’ll see the <strong>age</strong> disappears — that’s because our <code>showAge</code> variable has been initialised with <code>false</code>. If we initialise our <code>showAge</code> variable with <code>true</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [showAge, setShowAge] = useState(<span class="hljs-literal">true</span>);
</code></pre>
<p>The age will appear on the contact card. Nice! Although, its not great — we don’t want to change the code whenever we want to show the age on the contact card! </p>
<p>Before we look at how to dynamically change our <code>showAge</code> variable, lets tidy the code a bit. Go ahead and replace this line:</p>
<pre><code class="lang-js">{showAge === <span class="hljs-literal">true</span> ? <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span> : <span class="hljs-literal">null</span>}
</code></pre>
<p>With:</p>
<pre><code class="lang-js">{showAge &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 25<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span> }
</code></pre>
<p>This gives the same result, just in a more concise way.</p>
<blockquote>
<p>TIP: Shorten code where it makes sense to, don’t feel like you have to shorten every line of code you write! Readability should come first. </p>
</blockquote>
<h2 id="heading-updating-state">Updating State</h2>
<p>Ok back to updating state. If we remember back, the <code>useState()</code> hook gives us a <strong>function to update the state</strong>. Let’s wire this up to a button, which, when clicked, will toggle showing the age on the contact card.</p>
<p>We can do this with the following:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> setShowAge(!showAge)}&gt;
    Toggle Age 
&lt;/button&gt;
</code></pre>
<p>What this is doing is calling the <strong>setShowAge function</strong> (which we get from the useState hook) to change the <strong>value of show age to the opposite of what it currently is</strong>.</p>
<blockquote>
<p>NOTE: I’m using the <strong>Arrow Function</strong> syntax here to pass a function to the <code>onClick</code> property. If you’re not familiar we this, a quick reminder that you can get my [book where I discuss the important bits of JavaScript to know before React here].</p>
</blockquote>
<p>When the state updates, React will <strong>re-render the component</strong> and since the value of <code>showAge</code> is true, the age will be displayed. </p>
<p>If the user clicks the button again, this will set <code>showAge</code> to <code>false</code>, React will re-render the component, and the age will be hidden:</p>
<p><img src="https://jschris.com/46201add1931d222dde4782768435378/age-toggle.gif" alt="age-toggle" width="600" height="400" loading="lazy"></p>
<p>Look at our fancy toggle in action! </p>
<blockquote>
<p>TIP: Whenever the components state changes, React will re-render the component with the new state</p>
</blockquote>
<p>Notice how even though we have 3 <strong>ContactCard</strong> components being rendered, when we click the button the age only displays for <strong>one</strong> of the cards, and not all of them. This is because <strong>state belongs to the individual component</strong>. In other words, each <strong>ContactCard</strong> component that renders is a <strong>copy</strong>, and has its own state/data.</p>
<h2 id="heading-introducing-props">Introducing Props</h2>
<p>So now we have a lovely new <strong>ContactCard</strong> component that we’re reusing a few times. Although its not really reusable, since the name, email, age and avatar are the same for each of our components. Oh dear! We can make this data more dynamic with what are called <strong>props</strong>. </p>
<p>Since you’re just getting started with React, you can think of<strong>Props</strong> as data that gets passed to a component, which the component can then use. For example, we can pass in our <strong>avatar</strong> , <strong> email</strong>, <strong>name</strong> and <strong>age</strong> as props to our <strong>Contact Card</strong> component like so:</p>
<pre><code class="lang-jsx">&lt;ContactCard
  avatar=<span class="hljs-string">"https://via.placeholder.com/150"</span>
  name=<span class="hljs-string">"Jenny Han"</span>
  email=<span class="hljs-string">"jenny.han@notreal.com"</span>
  age={<span class="hljs-number">25</span>}
/&gt;
</code></pre>
<p>As you can see, we define a prop by giving it a name. Eg. <em>name</em> and using the <strong>equals</strong> to assign some value to that prop e.g. <strong>Jenny Han</strong>.</p>
<p>We can have as many props as we want, and we can name these props whatever we want, so they’re pretty flexible. </p>
<p>Props can hold different types of data, i.e. strings, numbers, booleans, objects, arrays and so on. </p>
<blockquote>
<p>NOTE: Props must be defined using quoted text (e.g. name=“Jenny Han”) or within braces (e.g. <code>age={25}</code>. If we leave out the braces for anything other than strings things start to break — <code>age=25</code> );</p>
</blockquote>
<p>Go ahead and replace the current <strong>ContactCard</strong> components within  our <strong>App</strong> component with the following:</p>
<pre><code class="lang-jsx">&lt;ContactCard
  avatar=<span class="hljs-string">"https://via.placeholder.com/150"</span>
  name=<span class="hljs-string">"Jenny Han"</span>
  email=<span class="hljs-string">"jenny.han@notreal.com"</span>
  age={<span class="hljs-number">25</span>}
/&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
  <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
  <span class="hljs-attr">name</span>=<span class="hljs-string">"Jason Long"</span>
  <span class="hljs-attr">email</span>=<span class="hljs-string">"jason.long@notreal.com"</span>
  <span class="hljs-attr">age</span>=<span class="hljs-string">{45}</span>
/&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
  <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
  <span class="hljs-attr">name</span>=<span class="hljs-string">"Peter Pan"</span>
  <span class="hljs-attr">email</span>=<span class="hljs-string">"peter.pan@neverland.com"</span>
  <span class="hljs-attr">age</span>=<span class="hljs-string">{100}</span>
/&gt;</span></span>
</code></pre>
<p>All we’re doing here is passing <strong>the data that the component needs</strong> to each component as props. Notice how the data is different for each component.</p>
<h2 id="heading-using-props-within-a-component">Using Props within a component</h2>
<p>We’ve sent a bunch of props down to the <strong>ContactCard</strong> component, so let’s tell the <strong> ContactCard</strong> how to use them.</p>
<p>Until now, our <strong> ContactCard</strong> function doesn’t accept any <em>parameters</em>. React, being the magical thing that it is, automatically puts all our props into a lovely <strong>props object</strong>, that gets passed into the component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
    <span class="hljs-comment">//...other code</span>
};
</code></pre>
<p>Notice the <strong>props</strong> variable. This is an object containing the props we defined previously.  We can <em>access our defined props</em> by using the <em>dot notation</em> like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(props.avatar); 
    <span class="hljs-built_in">console</span>.log(props.name);
    <span class="hljs-built_in">console</span>.log(props.email);
    <span class="hljs-built_in">console</span>.log(props.age);

    <span class="hljs-comment">//...other code</span>
};
</code></pre>
<p>Finally, we want to replace the hardcoded values in our JSX, with the values we receive from the props:</p>
<pre><code class="lang-jsx"><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">"contact-card"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{props.avatar}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: {props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: {props.email}<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> setShowAge(!showAge)}&gt;Toggle Age <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      {showAge &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {props.age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>Notice how we have set the <strong>image source</strong> using whatever value we received from props. We did similar for <strong>name</strong>, <strong>email</strong>, and <strong>age</strong>.  Also notice how we wrap this code in <strong>curly braces</strong>, so it gets executed as JavaScript.</p>
<p>Our final <strong>App.js</strong> file looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
        <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"Jenny Han"</span>
        <span class="hljs-attr">email</span>=<span class="hljs-string">"jenny.han@notreal.com"</span>
        <span class="hljs-attr">age</span>=<span class="hljs-string">{25}</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
        <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"Jason Long"</span>
        <span class="hljs-attr">email</span>=<span class="hljs-string">"jason.long@notreal.com"</span>
        <span class="hljs-attr">age</span>=<span class="hljs-string">{45}</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
        <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"Peter Pan"</span>
        <span class="hljs-attr">email</span>=<span class="hljs-string">"peter.pan@neverland.com"</span>
        <span class="hljs-attr">age</span>=<span class="hljs-string">{100}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> ContactCard = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> [showAge, setShowAge] = 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">"contact-card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{props.avatar}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"profile"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"user-details"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: {props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: {props.email}<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> setShowAge(!showAge)}&gt;
            Toggle Age 
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        {showAge &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {props.age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>If you run this in the browser, you should see something similar to this:</p>
<p><img src="https://jschris.com/static/a01167e9d19e96ec4689edbe74bfbdcc/d56e1/contact-lists-3-components.png" alt="contact-lists-3-components" width="600" height="400" loading="lazy"></p>
<p>Hurray! Our component works the same as before, but its now more dynamic. We can reuse the same <strong>ContactCard</strong> but passing in different data — whilst keeping the layout, styles, and state objects the same.</p>
<h2 id="heading-rendering-components-from-a-list">Rendering components from a List</h2>
<p>Our contacts list is coming along nicely, we have some well crafted, reusable code so time to leave it alone right? Wrong! Let’s take it a step further.</p>
<p>In a real application, data usually comes in the form of an array of data, e.g. after an API call. Let’s pretend we’ve made an API call to <strong>retrieve some users from a database</strong> and have received the following data:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> contacts = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Jenny Han"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"jenny.han@notreal.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Jason Long"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"jason.long@notreal.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">45</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Peter Pan"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"peter.pan@neverland.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">100</span> }
];
</code></pre>
<p>Paste this into the <strong>App()</strong> component at the top of the function. The eagled eye amongst you will notice how this data is similar to what we already have. But how we we turn this data into <strong>ContactCard</strong> components? Well, remember all those days you spent learning how to loop over an array using <strong>.map()</strong>? Now is the day we put that into action!</p>
<p>To display a list of components, we:</p>
<p>1) Loop over the array using <strong>.map()</strong>
2) For each item in the array, create a new <strong>ContactCard component</strong>
3) Pass the data from each object in the array to the <strong>ContactCard component</strong> as props</p>
<p>Let’s see how this works. In our app<strong>App()</strong> component, replace the <strong>return</strong> statement with this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
    {contacts.map(contact =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
        <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">{contact.name}</span>
        <span class="hljs-attr">email</span>=<span class="hljs-string">{contact.email}</span>
        <span class="hljs-attr">age</span>=<span class="hljs-string">{contact.age}</span>
      /&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/&gt;</span></span>
);
</code></pre>
<p>As you can see, we <strong>map over the array</strong>. For each object in the array, we want to create a new <strong>ContactCard</strong> component. For the props, we want to take the <strong>name</strong>,  <strong>email</strong>, and <strong>age</strong> from the <strong>current object the map function is on</strong>. In other words, from the <strong>contact</strong> variable.</p>
<blockquote>
<p>NOTE: I’ve left the “avatar” prop alone, as this is the same for now — it’ll change later in the tutorial</p>
</blockquote>
<p>And that’s it! Our <strong>App.js</strong> file looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//App.js</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> contacts = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Jenny Han"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"jenny.han@notreal.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Jason Long"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"jason.long@notreal.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">45</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Peter Pan"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"peter.pan@neverland.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">100</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Amy McDonald"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"amy@email.com"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">33</span> }
  ];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {contacts.map(contact =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
          <span class="hljs-attr">avatar</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">{contact.name}</span>
          <span class="hljs-attr">email</span>=<span class="hljs-string">{contact.email}</span>
          <span class="hljs-attr">age</span>=<span class="hljs-string">{contact.age}</span>
        /&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>Run this in the browser and things should look the same. We haven’t changed our <strong>ContactCard</strong>, merely changed where we got the data from. The cool thing about this is that if you added another row to the <strong>contacts</strong> array,  the extra component will get rendered automatically — you don’t have to do anything else! Try this for yourself and see.</p>
<h2 id="heading-pulling-data-from-an-api">Pulling data from an API</h2>
<p>We’ve got a nice looking React App now. It's dynamic and things are working well. Which is a good place to be since we’re just getting started with React! But there are some tidy ups we need to make. In a real application, <strong>data will be pulled in from an API</strong>.</p>
<p>For the next part of the tutorial, we are going to get real contacts (when I say real contacts, I mean fake contacts — you know what I mean) from a real API: <a target="_blank" href="https://randomuser.me/">https://randomuser.me/</a>. Feel free to browse the website and look at the response we will get back — this is where we will get our data to populate our components.</p>
<p>Firstly, let’s create a <strong>state variable</strong> to hold the data we get back from the API. Remember, state is good for holding that that can change. Our contacts list can definitely change!</p>
<p>In <strong>App.js</strong>, remove the <strong>contacts</strong> array add the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [contacts, setContacts] = useState([]);
</code></pre>
<p>Here, we’re doing here is creating a state object, and initialising it to an empty array. When we make the API call, we’ll update the state to contain a list of contacts. Since we named this state object <strong>contacts</strong>, our rendering logic within the JSX will look for this array instead (as opposed to the old <strong>contacts</strong> array we just deleted).</p>
<p>Next, let’s grab the data from the API.  We’ll use the standard <strong>Fetch API</strong>. For now, we’ll log the data to the console. Add the following below the state object we just created:</p>
<pre><code class="lang-js">fetch(<span class="hljs-string">"https://randomuser.me/api/?results=3"</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  });
</code></pre>
<p>All we’re doing here is:</p>
<ul>
<li>Making a GET request to the <strong>randomuser</strong> API, asking for <strong>three</strong> results</li>
<li>Convert the response into <strong>JSON</strong></li>
<li>Logging the <strong>JSON</strong> to the console.</li>
</ul>
<p>If you run this in the browser, you’ll notice the <strong>ContactCard</strong> components no longer render - thats fine, we haven’t saved any new data to state yet, and our state variable is currently empty. If you look at the console (in your browser dev tools) you’ll notice the response object is logged. Which will look something like this:</p>
<p><img src="https://jschris.com/static/2327d21e950dd2b2d3a0c7c51fac655d/587b0/response_object.png" alt="response_object" width="600" height="400" loading="lazy"></p>
<p>You’ll see we have a <strong>results</strong> array, which has 3 objects. Each of these objects contain the details of a user (or a “Contact” in our case). This is similar to the <strong>contacts</strong> array we manually created ourselves in the previous section - just an array full of objects. </p>
<p>Let’s update our <strong>App</strong> components JSX to pick data from this object. Update the JSX like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
    {contacts.map(contact =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
        <span class="hljs-attr">avatar</span>=<span class="hljs-string">{contact.picture.large}</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">{contact.name.first</span> + " " + <span class="hljs-attr">contact.name.last</span>}
        <span class="hljs-attr">email</span>=<span class="hljs-string">{contact.email}</span>
        <span class="hljs-attr">age</span>=<span class="hljs-string">{contact.dob.age}</span>
      /&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/&gt;</span></span>
);
</code></pre>
<p>This works similar to what we had before:</p>
<ul>
<li>We are looping through the <strong>contacts</strong> variable (which, at the moment is an empty array)</li>
<li>When we eventually save the response to state (the next step) we look through each object in the array, for the appropriate things we need: in this case <strong>picture, name, email, and dob</strong> objects.  </li>
</ul>
<p>Next we want to store the <strong>results</strong> array in state, so our JSX can loop over it (using the <strong>map()</strong> function we seen previously) and render some lovely <strong>ContactCards</strong>. Within our <strong>fetch</strong> function, add the call to <strong>setContacts(data.results)</strong> like so:</p>
<pre><code class="lang-jsx">fetch(<span class="hljs-string">"https://randomuser.me/api/?results=3"</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
    setContacts(data.results);
  });
</code></pre>
<p>Our <strong>App</strong> component now looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//App.js</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [contacts, setContacts] = useState([]);

fetch(<span class="hljs-string">"https://randomuser.me/api/?results=3"</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
    setContacts(data.results);
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {contacts.map(contact =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
          <span class="hljs-attr">avatar</span>=<span class="hljs-string">{contact.picture.large}</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">{contact.name.first</span> + " " + <span class="hljs-attr">contact.name.last</span>}
          <span class="hljs-attr">email</span>=<span class="hljs-string">{contact.email}</span>
          <span class="hljs-attr">age</span>=<span class="hljs-string">{contact.dob.age}</span>
        /&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p> If you save this, and run it in the browser, you’ll see something like this:</p>
<p><img src="https://jschris.com/4bd02a07f80d45810780b5db77db42b3/multiple-calls-to-api.gif" alt="multiple-calls-to-api" width="600" height="400" loading="lazy"></p>
<p>You might be thinking, “WTF is going on? Everything is broken!” </p>
<p>Don’t panic just yet. (If you’re on a slower machine or just getting a bit freaked out, you can comment out the <strong>setContacts(data.results)</strong> line within the <strong>fetch</strong> function for now).</p>
<p>What’s happening here is that we’re stuck in a bit of a loop:</p>
<p>1) We make a call to <strong>fetch</strong> and get some data back 
2) We then <strong>save this data to state</strong>
3) Remember, React does a <strong>re-render when the state changes</strong>
4) When the component re-renders, the <strong>fetch</strong> api call happens again, and sets the state
5) Since the state updated, the component re-renders again
6) After the component re-renders, fetch is called again…
7) You get the idea</p>
<p>So how do we stop this? We have to delete everything and start again. Nah just kidding, don’t run away yet. We can fix this with another built in React Hook - <strong>useEffect</strong>.</p>
<h2 id="heading-introducing-useeffect">Introducing useEffect</h2>
<p>The <strong>useEffect</strong> hook is a special hook that runs a function. By default, the useEffect hook runs on every re-render. However, we can configure it to only run <strong>under certain condition</strong>, e.g. when a <strong>component mounts</strong>, or <strong>if a variable changes</strong>. The useEffect hook looks like this:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// code to run </span>
});
</code></pre>
<p>This will run every time. If we want to specify <strong>“only run once”</strong> we pass in an <strong>empty array</strong> as a second argument like so. </p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// code to run </span>
},[]); <span class="hljs-comment">//&lt;-- notice the empty array</span>
</code></pre>
<p>This is called a <strong>dependency array</strong>. When the dependency array is empty, this means the useEffect function will only run when the component loads for the first time. For additional re-renders, the useEffect function is skipped. </p>
<p>This is a perfect place to put our API call, as we only want to get the data once, when the component loads. Go ahead and place a <strong>useEffect()</strong>function into our <strong>App</strong> component, and move the <strong>fetch</strong> API call into the useEffect function. Our  <strong>App</strong> component now looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//App.js</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [contacts, setContacts] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(<span class="hljs-string">"https://randomuser.me/api/?results=3"</span>)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
        setContacts(data.results);
      });
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {contacts.map(contact =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">ContactCard</span>
          <span class="hljs-attr">avatar</span>=<span class="hljs-string">{contact.picture.large}</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">{contact.name.first</span> + " " + <span class="hljs-attr">contact.name.last</span>}
          <span class="hljs-attr">email</span>=<span class="hljs-string">{contact.email}</span>
          <span class="hljs-attr">age</span>=<span class="hljs-string">{contact.dob.age}</span>
        /&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>Now, if you run the code in your browser, you should see 3 contact cards appear! Refresh the page to see another randomised list of contacts:</p>
<p><img src="https://jschris.com/static/093da2b0c6947b52d83b42183d172718/6569d/contacts-list-intro.png" alt="contacts-list-intro" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congrats! You just completed your first real-world app and laid the foundation to move on to more advanced topics. </p>
<p><a target="_blank" href="https://subscribe.jschris.com">Make sure to subscribe here to stay up to date with my latest React content, course discounts and early access, as well as some free stuff!</a></p>
<p><a target="_blank" href="https://www.jschris.com">Also don't forget to check out my new blog - www.jschris.com - where I'll be posting JavaScript/React related articles and tutorials!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Beginner's Guide to Bug Squashing: How to Use Your Debugger and other tools to find and fix bugs ]]>
                </title>
                <description>
                    <![CDATA[ As web developers, it often feels like we spend more time fixing bugs and trying to solve problems than we do writing code. In this guide we'll look at some common debugging techniques, so let's get stuck in. "Fail to prepare, prepare to fail" What b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-beginner-bug-squashing-guide/</link>
                <guid isPermaLink="false">66c8c908e9e57963a5d82acc</guid>
                
                    <category>
                        <![CDATA[ 100DaysOfCode ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ bugs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Junior developer  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chris Blakely ]]>
                </dc:creator>
                <pubDate>Thu, 05 Dec 2019 15:46:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/bug.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As web developers, it often feels like we spend more time fixing bugs and trying to solve problems than we do writing code. In this guide we'll look at some common debugging techniques, so let's get stuck in.</p>
<h3 id="heading-fail-to-prepare-prepare-to-fail">"Fail to prepare, prepare to fail"</h3>
<p>What better way to start an article than with an old cliche! Bug's and issues are going to pop up. There is simply no way of getting away from this (sorry). With some simple planning, there are ways in which we can <em>minimize</em> the complexity and number of problems we face.</p>
<h2 id="heading-break-the-task-up-into-smaller-tasks">Break the task up into smaller tasks</h2>
<p>Now, I get it, we all like to get very excited and dive straight into our coding projects. The thing is, without some sort of plan we are creating problems for ourselves before we even start! </p>
<p>If I said to you, "you have to build a shopping list app", and you started coding straight away, what would happen? You would end up staring at a blinking cursor wondering how or what to do first, cursing my name under your breath for asking you to do such a task.</p>
<p>It's always easier to take a large problem and break it up into many smaller problems. For example, we can break the shopping list project into smaller tasks:  </p>
<ul>
<li>Create a form to add an item to the list</li>
<li>Allow a user to remove an item from the list</li>
<li>Display a total number of items in the list</li>
</ul>
<p>You can even break these tasks up into more detailed tasks. For example, for the first task in our list, our first, "little mini task" (should I trademark that term?) could be:</p>
<p>1) Create an input field to capture the item name</p>
<p>2) Create a button that calls a functions <code>addToList()</code> when clicked</p>
<p>3) Write logic within the <code>addToList()</code> function that adds the item to the list</p>
<p>And so on. You get the idea. I prefer breaking work up like this as it really makes me think about the problems I'll encounter <em>early</em> and the solutions (<a target="_blank" href="https://www.freecodecamp.org/news/a-walk-through-the-developer-thought-process/">I've written an in-depth article about this here</a>) before I've written any code. It also helps me understand what I'm trying to do, and puts me in the "zone". It's much easier to solve problems that arise when you understand what you are trying to achieve.</p>
<h2 id="heading-be-prepared-to-purge-your-code">Be prepared to purge your code</h2>
<p>To make an omelet, we have to break a few eggs. This means being prepared to completely re-write our code to get it working. </p>
<p>I bet you're thinking, "oh man, it took me days/weeks/millennia to get this far with my code, and now I have to delete it?!"  Um, yeah. Sometimes. Sorry. The reality with web development is that code will change all the time, for various reasons - bugs, code reviews, changes in requirements, boredom, etc.</p>
<p>Sometimes we feel so precious about our code and can't bear to delete it, that we try and overcome problems by trying to "fit a round peg into a square hole". We think "NOO! I can't possibly delete this method. It took me forever. There has got to be a way!" This mental block causes our own problems - because by simply rewriting what we currently have, we could find the solution to our problems.</p>
<p>Now that we're nice and prepared, let's look at what happens when things do go wrong.</p>
<h2 id="heading-error-messages-are-good">Error messages are good</h2>
<p>What's worse than seeing an error message when something goes wrong? Not seeing <em>any error message</em> when something goes wrong. Even though it's a daunting feeling to see a big red stack trace when we run our carefully crafted code, error messages are there to say "yeah, things are messed up right now, but here are some places you can look to start fixing it". </p>
<p>If we have a look at this example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> animals;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addAnimal</span>(<span class="hljs-params"></span>)</span>{
    animals.push(<span class="hljs-string">'elephant'</span>);
}

addAnimal();
</code></pre>
<p>Now let's have a look at the error:</p>
<pre><code><span class="hljs-built_in">TypeError</span>: Cannot read property <span class="hljs-string">'push'</span> <span class="hljs-keyword">of</span> <span class="hljs-literal">undefined</span>
at addAnimal (https:<span class="hljs-comment">//vanilla.csb.app/src/index.js:8:11) </span>
at evaluate (https:<span class="hljs-comment">//vanilla.csb.app/src/index.js:11:1) </span>
at $n (https:<span class="hljs-comment">//codesandbox.io/static/js/sandbox.acff3316.js:1:148704)</span>
</code></pre><p>I've left out some of the stack trace as most of it is, well, gibberish. Depending on how your frontend project handles error messages, you may even see the error in your browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-20-at-17.00.45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Look at that beauty of an error!</em></p>
<p>The important parts of the stack trace are usually at the top - the message, the function, and the line number, and our browser shows us this as well. So the interpreter does it's best to tell us what's wrong. It's a shame it can't solve the problem for us, eh?</p>
<p>So, we've finished having our panic attack at seeing the error and have picked some information from the error message. If we break it down we can see this line:</p>
<pre><code>Cannot read property <span class="hljs-string">'push'</span> <span class="hljs-keyword">of</span> <span class="hljs-literal">undefined</span>
</code></pre><p>This usually means that there is a variable not defined or initialized somewhere. BUT WHERE?!?</p>
<p>If we continue reading the stack trace, we see the error occurs within the <code>addAnimal()</code> function. We can see that we are trying to push a new animal to an array - ah! I forgot to initialize the <code>animals</code> array. Doh! Our fixed code looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> animals = [];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addAnimal</span>(<span class="hljs-params"></span>) </span>{
    animals.push(<span class="hljs-string">"elephant"</span>);
}

addAnimal();
</code></pre>
<p>The error thrown in the browser will show you the problem quicker, but not all frontend projects will be configured to do this, and backend developers do not have this luxury.  This is why I recommend learning to read the stack trace.</p>
<h2 id="heading-to-defeat-the-bug-you-must-think-like-the-bug">To defeat the bug, you must think like the bug</h2>
<p>The stack trace gives you an idea of what the error is. Well, sometimes it does and sometimes it doesn't. What if you see an error message that looks more like cave glyphs than English? Or what if there is no error, but your code is simply not acting as you thought?</p>
<p>It's time to get the debugger out. Let's walk through another example. But first some context! </p>
<p>Mr. Bob CEO (who is a CEO, who would have thought?!) approaches you and says,</p>
<p>"Hey, I have an amazing idea for a product.</p>
<ul>
<li>I want a web app that allows the user to enter a number.</li>
<li>If the number is less than 5, the message should read "UNDER".</li>
<li>If the number is equal to or more than 5, the message should read "OVER".</li>
</ul>
<p>This is a million-dollar idea and I want you to build it for me".</p>
<p>"OKAY!" You say, and you get to work. </p>
<p><strong><em><em>Coding montage with dramatic music plays as time fast forwards</em></em></strong></p>
<p>You've completed the code for your web app. Huzzah!</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>

<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">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My super awesome number app<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"The HTML5 Herald"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"SitePoint"</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">head</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">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"number-input"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"number-input-submit-button"</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">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"number-display"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./index.js"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</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>
</code></pre>
<pre><code class="lang-javascript">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> numberInputSubmitButton = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"number-input-submit-button"</span>)

    numberInputSubmitButton.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

        <span class="hljs-keyword">const</span> numberInputValue = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"number-input"</span>).value;

        <span class="hljs-keyword">let</span> text;
        <span class="hljs-keyword">if</span>(numberInputValue &gt; <span class="hljs-number">5</span>) {
            text = <span class="hljs-string">"OVER"</span>;
        } <span class="hljs-keyword">else</span> {
            text = <span class="hljs-string">"UNDER"</span>;
        }

        <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"number-display"</span>).innerHTML = text
    });
})();
</code></pre>
<p>(Note: You may have spotted the bug already. If you did, let's pretend you didn't. If you haven't noticed the bug, that's OK.)</p>
<p>Time to start testing. Let's run through some use cases for our business logic.</p>
<p>1) User enters 3:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-20-at-17.18.36.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>2) User enters 7</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-19-at-09.38.25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So far so good! But what happens if we enter 5?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-19-at-09.38.35.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>OH NO! A bug! The text displayed is incorrect, it should display "<strong>OVER</strong>" but instead displays "<strong>UNDER</strong>". Hmm, no error messages, and I can't seem to see in the code what is wrong. <strong>Let's run the debugger and step through the code.</strong></p>
<h3 id="heading-using-the-debugger">Using the debugger</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-19-at-09.39.41.png" alt="Image" width="600" height="400" loading="lazy">
<em>Note the "variables" panel on the left - this can be a life saver</em></p>
<p>A good place to start is to put a <strong>breakpoint as close to the buggy code as possible.</strong> You can determine this by reading the code, error messages, or if you have that "<em>ah-ha!</em> <em>I know which method is causing this</em>" moment. From here, it's a case of stepping through the code, inspecting the variables, and checking if the correct code branches are run. </p>
<p>In our example, I have put a breakpoint at the start of my <code>if statement</code> - as this is where the failing logic is.</p>
<p>Once I start debugging, chrome opens and I can replicate the issue by entering "5" and clicking submit. This hits the breakpoint, and immediately there are a few things to note:  </p>
<ul>
<li>The debugger stops at the breakpoint, so this means I'm on the right track</li>
<li>This also means that the function is being called correctly, and event handlers are working as expected</li>
<li>I can also see that the user input is being captured correctly (from the "variables" panel on the left-hand side, I can see that "5" was entered)</li>
</ul>
<p>So far so good, no immediate issues to worry about. Well, code related ones anyway. Next, I'll press <strong>F10 to step through the code</strong>. This runs each statement individually, allowing us to inspect elements, variables, and other things at our own pace. Isn't technology just fabulous? </p>
<p>Remember since I expect the message "OVER" to appear when the user enters "5", I'm expecting the debugger to take me into the first branch of the if statement...</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screenshot-2019-11-19-at-09.39.58.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>BUT NO! I'm brought into the second branch. Why? I need to amend the conditional to read "<strong>more than or equals to"</strong> as opposed to <strong>"more than".</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span>(numberInputValue &gt;= <span class="hljs-number">5</span>) {
    text = <span class="hljs-string">"OVER"</span>;
} <span class="hljs-keyword">else</span> {
    text = <span class="hljs-string">"UNDER"</span>;
}
</code></pre>
<p>Success! Our bug is fixed. Hopefully this gives you an idea on how to walk through the code, making use of VSCodes awesome debugging tools.</p>
<h2 id="heading-more-debugging-tips">More Debugging tips</h2>
<ul>
<li>If your breakpoints aren't being hit, this could be part of the issue. Make sure the correct functions or event handlers are being called in the way you expect</li>
<li>You can <code>step over</code> functions you want to skip. If you want to debug any functions you come across, use the <code>step into</code> command</li>
<li>Watch out for variables, parameters, and arguments as you are stepping through your code. Are the values what you expect?</li>
<li>Write code in a way that is easier to read/debug. It might look cool to have your code on one line, but it makes debugging harder</li>
</ul>
<h3 id="heading-google-is-your-friend">Google is your friend</h3>
<p>Ok so we've looked at the stack-trace, tried debugging, and we're still stuck with this bug. The only thing left to do now is make a sacrifice to the coding gods and hope things fix themselves! </p>
<p>Or I guess we could use Google. </p>
<p>Google is a treasure trove of software development problems and solutions, all at our fingertips. It can be sneakily difficult to access this information though, as you have to know how to Google the right things to get the right information! So how do we effectively use Google?</p>
<p>Let's look back to our first example - you've read the stack trace, looked at the code, but the message <code>Cannot read property 'push' of undefined</code> is still driving you mad. Bewildered, you take to Google in hopes of finding an answer. Here are some things to try:</p>
<p><strong>Copy and paste the error message.</strong> Sometimes this works, depending on how "generic" the error message is. For example, if you get a <strong>Null pointer exception</strong> (who doesn't love those?), Googling "Null pointer exception" might not return very helpful results.</p>
<p><strong>Search for what you are trying to do.</strong> For example, <em>"How to create an array and add an item to the end"</em>. You might find some generous developer has posted a solution using best practices on StackOverflow, for example. You might also find this solution is completely different from yours - remember what I said about being comfortable purging your code? </p>
<p>A side note on using someone else's code - try and avoid blindly copying and pasting, make sure you understand what the code does first!</p>
<h3 id="heading-ask-for-help-the-right-way">Ask for help the right way</h3>
<p>Hopefully, after a mix of debugging, stack trace investigating, and Googling you have seen the light at the end of the tunnel and solved your problem. Unfortunately, depending on what you are trying to do, you still might be a bit stumped. This is a good time to seek advice from other people. </p>
<p>Now, before you run into the street screaming "my code is broken please help me!", it's important to know the best way to ask for help. Asking for help in the right way makes it easier for people to understand the problem and help you solve it. Let's look at some examples:</p>
<p><strong>Bad</strong> - "My code is broken and I don't know what's wrong."</p>
<p><strong>Good</strong> - "I'm trying to add an item to the end of an array in JavaScript, and I'm getting this error message: Cannot read property 'push' of undefined. Here's my code so far."</p>
<p>See how the "Good" example is much more informative? More information makes it easier for other kindhearted devs to help you out. This is a good habit to get into as it not only benefits you when you are learning to code but also in your first job when you need to ask for help.</p>
<p>So where can you ask for help?  </p>
<ul>
<li>StackOverflow</li>
<li>Twitter</li>
<li>Slack groups</li>
<li>Colleagues or developer friends</li>
</ul>
<p>Quick Tip: You can use a tool like <a target="_blank" href="https://www.freecodecamp.org/news/the-beginner-bug-squashing-guide/codesandbox.io">CodeSandbox.io</a> or <a target="_blank" href="https://www.freecodecamp.org/news/the-beginner-bug-squashing-guide/codepen.io">CodePen.io</a> to recreate your problem and share it with people.</p>
<h3 id="heading-practice-practice-practice">Practice, practice, practice</h3>
<p>Just like Rome wasn't built in a day (well, it could have been for all I know) you will not become king bug squasher overnight. As your career goes on and your experience grows, you'll be armed with a wealth of knowledge that helps you solve bugs and issues faster. I regularly find myself saying "ah, I've solved that before" or "oh yeah, I have a StackOverflow link that helps me here" and the whole thing becomes a lot easier. So keep practicing, and this skill will grow naturally.</p>
<p>Thanks for reading! If you enjoyed this article, <a target="_blank" href="https://subscribe.chrisblakely.dev/">why not subscribe to my newsletter</a>? </p>
<p>Every week I send out a <strong>list of 10 things</strong> I think are worth sharing — my latest articles, tutorials, tips and interesting links for upcoming developers like you. I also give out some free stuff from time to time :) </p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
