<?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[ Yogesh Chavan - 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[ Yogesh Chavan - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 18 May 2026 22:34:27 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/yogeshchavan97/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Debug Node.js Applications Using the debugger; Statement ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will learn the easiest and most efficient way to debug Node.js application code. So let's get started. Want to watch the video version of this tutorial? You can check out the video below: https://www.youtube.com/watch?v=B_oPWQ9W... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-debug-node-js-applications/</link>
                <guid isPermaLink="false">66bc551360ad5c1520c166e8</guid>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Mon, 22 Apr 2024 19:50:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/debug_node_js_code_thumbnail-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will learn the easiest and most efficient way to debug Node.js application code.</p>
<p>So let's get started.</p>
<p>Want to watch the video version of this tutorial? You can check out the video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/B_oPWQ9Wyew" 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-table-of-contents">Table Of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-how-you-usually-debug-nodejs-applications">How You Usually Debug Node.js Applications</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-a-debugger-to-debug-your-code">How to Add a Debugger to Debug Your Code</a></li>
<li><a class="post-section-overview" href="#heading-how-to-run-the-application-for-debugging">How to Run the Application for Debugging</a></li>
<li><a class="post-section-overview" href="#heading-how-to-access-variables-during-debugging">How to Access Variables During Debugging</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-script-to-debug-nodejs-apps">How to Create a Script to Debug Node.js Apps</a></li>
<li><a class="post-section-overview" href="#heading-quick-recap">Quick Recap</a></li>
</ul>
<h2 id="heading-how-you-usually-debug-nodejs-applications"><strong>How You Usually Debug Node.js Applications</strong></h2>
<p>If you want to debug a Node.js application, usually you add a <code>console.log</code> statement in the code that you want to debug to find out the value of any variable.</p>
<p>This works, but you need to keep checking the console log to see the value that you're trying to print.</p>
<p>And if the data printed in the console contains nested objects or if it's a lot of data, then using <code>console.log</code> is not feasible.</p>
<p>Fortunately, there's a better way.</p>
<h2 id="heading-how-to-add-a-debugger-to-debug-your-code"><strong>How to Add a Debugger to Debug Your Code</strong></h2>
<p>Instead, you can add a <code>debugger;</code> statement in the code that you want to debug.</p>
<p>So let's say you have an Express.js API route for registering a user as shown in the below code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// controllers/auth.js</span>

<span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { email, password } = req.body;
    <span class="hljs-keyword">const</span> existingUser = <span class="hljs-keyword">await</span> User.findOne({
      email,
    });
    <span class="hljs-keyword">if</span> (existingUser) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">'User with the provided email already exist'</span>);
    }
    <span class="hljs-comment">// some more code</span>
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">201</span>).send();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
    <span class="hljs-keyword">return</span> res
      .status(<span class="hljs-number">500</span>)
      .send(<span class="hljs-string">'Error while registering a new user. Try again later.'</span>);
  }
};

<span class="hljs-built_in">module</span>.exports = { register };

<span class="hljs-comment">// routes/auth.js</span>
<span class="hljs-keyword">const</span> { register } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../controllers/auth'</span>);

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

Router.post(<span class="hljs-string">'/api/register'</span>, register);
</code></pre>
<p>And there's some issue while registering a user, so you want to debug the <code>register</code> function's code.</p>
<p>In that case, you can just add a <code>debugger;</code> statement inside the <code>register</code> function code like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { email, password } = req.body;
    <span class="hljs-keyword">debugger</span>;
    <span class="hljs-keyword">const</span> existingUser = <span class="hljs-keyword">await</span> User.findOne({
      email,
    });
    <span class="hljs-keyword">if</span> (existingUser) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send(<span class="hljs-string">'User with the provided email already exist'</span>);
    }
    <span class="hljs-comment">// some more code</span>
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">201</span>).send();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
    <span class="hljs-keyword">return</span> res
      .status(<span class="hljs-number">500</span>)
      .send(<span class="hljs-string">'Error while registering a new user. Try again later.'</span>);
  }
};
</code></pre>
<h2 id="heading-how-to-run-the-application-for-debugging"><strong>How to Run the Application for Debugging</strong></h2>
<p>Normally, you start your Node.js application by executing the following command:</p>
<pre><code class="lang-javascript">node index.js
</code></pre>
<p>But instead, you can execute the following command:</p>
<pre><code class="lang-javascript">node inspect index.js
</code></pre>
<p>Here, we just added an <code>inspect</code> keyword in between.</p>
<p>If your main application file's name is <code>server.js</code>, you can execute the <code>node inspect server.js</code> command.</p>
<p>Once you execute the above command, you will see the output displayed as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_debugger_output.png" alt="Image" width="600" height="400" loading="lazy">
<em>Debugger Attached</em></p>
<p>As you can see from the output, the debugger is attached, so now you can start debugging the code.</p>
<p>To do that, open the Chrome browser and enter <code>chrome://inspect</code> in the browser URL.</p>
<p>You will see the output as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/2_chrome_inspect.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chrome Inspect Page</em></p>
<p>Since you executed the <code>node inspect index.js</code> command to start inspecting, you can see a new target entry displayed under the <code>Remote Target</code> section.</p>
<p>Now, if you click on the displayed blue <code>inspect</code> link, then you will see a new browser dev tool opened as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/3_debugger_started.png" alt="Image" width="600" height="400" loading="lazy">
<em>Debugger Paused</em></p>
<p>As you can see in the right panel in the above image, the <code>Debugger paused</code> message is displayed. The debugging control is at the first line of code, as you can see from the highlighted yellow line.</p>
<p>But you don't want to start debugging from the first line of code. Instead, you want to just debug the registration code. To do this, click on the blue triangle icon which is displayed just above the <code>Debugger paused</code> message as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/4_debugging_stopped.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Continuing Debugging</em></p>
<p>Now don't close this window – instead, try registering a user from the application or making an API call using Postman, so the <code>/register</code> route handler code that we added previously will be executed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/5_registering_user.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Registering User &amp; Debugging Code</em></p>
<p>As you can see above, when you click on create new account button, you're automatically redirected to the code where you added the <code>debugger;</code> statement.</p>
<p>Now, you can debug the code line by line and see the values of each variable during debugging to find out and fix the issue.</p>
<h2 id="heading-how-to-access-variables-during-debugging"><strong>How to Access Variables During Debugging</strong></h2>
<p>Sometimes when you mouse over any variable while debugging to see its actual value, the value might be too long (because it might be an object with many properties), so you can't see it easily by mousing over it.</p>
<p>In that case, while the debugger is still active, you can open the console tab and type the name of the variable whose value you want to see – as you can see in the below Gif:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/6_logging_variables_in_console.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Logging Variables In The Console</em></p>
<p>So that's how you can easily debug any of your Node.js application's code.</p>
<h2 id="heading-how-to-create-a-script-to-debug-nodejs-apps"><strong>How to Create a Script to Debug Node.js Apps</strong></h2>
<p>If you don't want to manually type the <code>node inspect index.js</code> command every time in the terminal, you can create a new <code>debug</code> script inside the <code>package.json</code> file like this:</p>
<pre><code class="lang-js"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"node index.js"</span>,
    <span class="hljs-string">"debug"</span>: <span class="hljs-string">"node inspect index.js"</span>,
    <span class="hljs-string">"dev"</span>: <span class="hljs-string">"nodemon index.js"</span>
},
</code></pre>
<p>So now, you can execute the <code>npm run debug</code> command to start your application in debug mode.</p>
<h2 id="heading-quick-recap"><strong>Quick Recap</strong></h2>
<p>To debug a Node.js application, you need to follow the below steps:</p>
<ul>
<li>Add a <code>debugger</code> statement inside the code that you want to debug.</li>
<li>Run the <code>node inspect index.js</code> or <code>node inspect server.js</code> command to start the application in debug mode.</li>
<li>Access the URL <code>chrome://inspect</code> in your Chrome browser.</li>
<li>Click on the <code>inspect</code> link under the <code>Remote Target</code> section.</li>
<li>Click on the blue triangle icon to skip debugging if you don't want to start debugging your application from the first line of the <code>index.js</code> or <code>server.js</code> file.</li>
<li>Make an API call or do something that will trigger the code where you added the <code>debugger;</code> statement. This way you can debug the code line by line and find out the issue.</li>
</ul>
<h2 id="heading-thanks-for-reading"><strong>Thanks for Reading</strong></h2>
<p>That's it for this tutorial. I hope you learned something new.</p>
<p>Want to watch the video version of this tutorial? You can check out <a target="_blank" href="https://www.youtube.com/watch?v=B_oPWQ9Wyew">this video.</a></p>
<p>If you want to master JavaScript, ES6+, React, and Node.js with easy-to-understand content, check out my <a target="_blank" href="https://www.youtube.com/@codingmastery_dev/">YouTube channel</a>. Don't forget to subscribe.</p>
<p>Want to stay up to date with regular content on JavaScript, React, and Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
<p><a href="https://www.youtube.com/watch?v=wcjCsMRZKxs" target="_blank"><img src="https://d31ezp3r8jwmks.cloudfront.net/7g60tc6qngrs80np7v12vana6w1s" alt="Learn How To Build Full Stack Link Sharing App Using MERN Stack" width="1600" height="900" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use TypeScript with React ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you will learn how to use TypeScript with React. By the end, you will have a solid understanding of how to write React code with TypeScript. Want to watch the video version of this tutorial? You can check out the video below: https:/... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-typescript-with-react/</link>
                <guid isPermaLink="false">66bc5532da80a491ea5a5f45</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Wed, 15 Nov 2023 18:53:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/introduction_to_typescript_with_react_cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you will learn how to use TypeScript with React.</p>
<p>By the end, you will have a solid understanding of how to write React code with TypeScript.</p>
<p>Want to watch the video version of this tutorial? You can check out the video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KmYoJmZs3sY" 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-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-getting-started">Getting Started</a></li>
<li><a class="post-section-overview" href="#heading-react-and-typescript-basics">React and TypeScript Basics</a></li>
<li><a class="post-section-overview" href="#heading-three-ways-of-defining-prop-types">Three Ways of Defining Prop Types</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-random-users-list-application">How to Create a Random Users List Application</a></li>
<li><a class="post-section-overview" href="#heading-how-to-store-the-users-list-in-state">How to Store the Users List in State</a></li>
<li><a class="post-section-overview" href="#heading-how-to-display-the-users-on-the-ui">How to Display the Users on the UI</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-separate-user-component">How to Create a Separate User Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-separate-file-for-type-declarations">How to Create a Separate File for Type Declarations</a></li>
<li><a class="post-section-overview" href="#heading-how-to-display-a-loading-indicator">How to Display a Loading Indicator</a></li>
<li><a class="post-section-overview" href="#heading-how-to-load-users-on-button-click">How to Load Users on Button Click</a></li>
<li><a class="post-section-overview" href="#heading-how-to-handle-the-change-event">How to Handle the Change Event</a></li>
<li><a class="post-section-overview" href="#heading-thanks-for-reading">Thanks for Reading</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this tutorial, here's what you should have:</p>
<ul>
<li>a basic knowledge of how to work with React</li>
<li>a basic understanding of writing TypeScript code</li>
</ul>
<h2 id="heading-getting-started"><strong>Getting Started</strong></h2>
<p>To get started with TypeScript, you first need to install TypeScript on your machine. You can do this by executing <code>npm install -g typescript</code> from the terminal or command prompt.</p>
<p>Now, we will create a <a target="_blank" href="https://vitejs.dev/">Vite</a> project using TypeScript.</p>
<pre><code class="lang-js">npm create vite
</code></pre>
<p>Once executed, you will be asked some questions.</p>
<p>For the project name, enter <code>react-typescript-demo</code>.</p>
<p>For framework, select <code>React</code>, and for variant select <code>TypeScript</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/1_create_project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Project Using Vite</em></p>
<p>Once you've created the project, open it in VS Code and execute the following commands from the terminal:</p>
<pre><code class="lang-js">cd react-typescript-demo
npm install
</code></pre>
<p>Now, let's do some code cleanup.</p>
<p>Remove the <code>src/App.css</code> file and replace the content of <code>src/App.tsx</code> file with the following content:</p>
<pre><code class="lang-javascript"><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>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>After saving the file, you might see the red underlines in the file as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/2_red_error.png" alt="Image" width="600" height="400" loading="lazy">
<em>TypeScript Version Error</em></p>
<p>If you get that error, just press <code>Cmd + Shift + P(Mac)</code> or <code>Ctrl + Shift + P(Windows/Linux)</code> to open the VS Code command palette and enter <code>TypeScript</code> text in the search box and select the option <code>TypeScript: Select TypeScript Version...</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/3_version_options.png" alt="Image" width="600" height="400" loading="lazy">
<em>VSCode Command Palette Options</em></p>
<p>Once selected, you will see options to select between the VS Code version and the workspace version as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/4_select_option.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select Use Workspace Version</em></p>
<p>From these options, you need to select <code>Use Workspace Version</code> option. Once you select that option, the error from the <code>App.tsx</code> file will be gone.</p>
<p>Now, open the <code>src/index.css</code> file and replace its contents with the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">font-family</span>: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">400</span>;

  <span class="hljs-attribute">font-synthesis</span>: none;
  <span class="hljs-attribute">text-rendering</span>: optimizeLegibility;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
  <span class="hljs-attribute">-webkit-text-size-adjust</span>: <span class="hljs-number">100%</span>;
}
</code></pre>
<p>Now, let's start the application by executing the <code>npm run dev</code> command.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/5_app_started.png" alt="Image" width="600" height="400" loading="lazy">
<em>Application Started</em></p>
<p>Now, click on the displayed URL and access the application. You will see the following initial screen with text <code>App</code> displayed in the browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699944017441/701358b4-4bdc-49de-b008-245ef71fc929.png" alt="Image" width="771" height="522" loading="lazy">
<em>Running Application</em></p>
<h2 id="heading-react-and-typescript-basics">React and TypeScript Basics</h2>
<p>When using React with TypeScript, the first thing you should know is the file extension.</p>
<p>Every React + TypeScript file needs to have a <code>.tsx</code> extension.</p>
<p>If the file does not contain any JSX-specific code, then you can use the <code>.ts</code> extension instead of the <code>.tsx</code> extension.</p>
<p>To create a component in React with TypeScript, you can use the <code>FC</code> type from the <code>react</code> package and use it after the component name.</p>
<p>So open the <code>src/App.tsx</code> file and replace it with the following contents:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> App: FC = <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>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>Now, let's pass some props to this <code>App</code> component.</p>
<p>Open <code>src/main.tsx</code> and pass a <code>title</code> prop to the <code>App</code> component as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.tsx'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)!).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> <span class="hljs-attr">title</span>=<span class="hljs-string">'TypeScript Demo'</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>However, with the added <code>title</code> prop, we now have a TypeScript error as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/7_prop_error.png" alt="Image" width="600" height="400" loading="lazy">
<em>Prop Error</em></p>
<h2 id="heading-three-ways-of-defining-prop-types">Three Ways of Defining Prop Types</h2>
<p>We can fix the above TypeScript error in three different ways.</p>
<ul>
<li>Declaring Types Using Interface</li>
</ul>
<p>The error is coming because we have added a <code>title</code> prop as a mandatory prop for the <code>App</code> component – so we need to mention this inside the <code>App</code> component.</p>
<p>Open the <code>src/App.tsx</code> file and replace its contents with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <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>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>As you can see above, we have added an extra interface <code>AppProps</code> to specify which props the component is accepting. We also used the <code>AppProps</code> interface after the <code>FC</code> in angle brackets.</p>
<p>It's a good practice and recommended to start the interface name with a capital letter like <code>AppProps</code> in our case.</p>
<p>Now, with this change, the TypeScript error will be gone as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/8_no_prop_error.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Adding Prop Types To Component</em></p>
<p>This is how we specify what props a particular component accepts.</p>
<ul>
<li>Declaring Types Using type</li>
</ul>
<p>We can also declare the props type using <code>type</code> keyword.</p>
<p>So open the <code>App.tsx</code> file and change the below code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <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>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>to this code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

type AppProps = {
  <span class="hljs-attr">title</span>: string;
};

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <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>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>Here, instead of the <code>interface</code> declaration, we used the <code>type</code> declaration. Now the code will work without any TypeScript error.</p>
<p>It's up to you which one you use. I always like to use an interface for declaring component types.</p>
<ul>
<li>Using Inline Type Declaration</li>
</ul>
<p>The third way of declaring a type is by defining inline types as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> App = <span class="hljs-function">(<span class="hljs-params">{ title }: { title: string }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>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>As you can see above, we have removed the use of <code>FC</code> as it's not needed, and while destructuring the <code>title</code> prop we defined the type of it.</p>
<p>So out of these three ways, you can use whichever way you want. I always prefer to use an interface with <code>FC</code>. That way, if I want to add more props later, the code will not look complicated (which will happen if you define inline types).</p>
<p>Now, let's use the <code>title</code> prop and display it on the UI.</p>
<p>Replace the contents of the <code>App.tsx</code> file with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>As you can see, we're using an interface with <code>FC</code>, and we're destructuring the <code>title</code> prop and displaying it on the screen.</p>
<p>Now, open the <code>src/index.css</code> file and add the following CSS inside it:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">text-align</span>: center;
}
</code></pre>
<p>If you check the application in the browser, you will see that the title with text <code>TypeScript Demo</code> is correctly getting displayed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/10_title_displayed.png" alt="Image" width="600" height="400" loading="lazy">
<em>Application Title Displayed Correctly</em></p>
<h2 id="heading-how-to-create-a-random-users-list-application">How to Create a Random Users List Application</h2>
<p>Now that you have a basic idea of how to declare component props, let's create a simple Random Users List Application that will display a list of 10 random users on the screen.</p>
<p>For that, we will be using the <a target="_blank" href="https://randomuser.me/">Random User Generator</a> API.</p>
<p>This is the API URL we will be using:</p>
<pre><code class="lang-javascript">https:<span class="hljs-comment">//randomuser.me/api/?results=10</span>
</code></pre>
<p>Let's first install the <a target="_blank" href="https://www.npmjs.com/package/axios">Axios</a> npm library so we can make an API call using it.</p>
<p>Execute the following command to install the Axios library:</p>
<pre><code class="lang-javascript">npm install axios
</code></pre>
<p>Once installed, restart the application by executing the <code>npm run dev</code> command.</p>
<p>Now, replace the contents of the <code>App.tsx</code> file with the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FC, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getUsers = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
          <span class="hljs-string">'https://randomuser.me/api/?results=10'</span>
        );
        <span class="hljs-built_in">console</span>.log(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      }
    };
    getUsers();
  }, []);

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>As you can see above, we have added a <code>useEffect</code> hook where we're making the API call to get the the list of users.</p>
<p>Now, if you open the console in the browser, you will be able to see the API response displayed in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/11_api_response.png" alt="Image" width="600" height="400" loading="lazy">
<em>API Response</em></p>
<p>As you can see, we're correctly getting a list of 10 random users and the actual users list is coming in the <code>results</code> property of the response.</p>
<h2 id="heading-how-to-store-the-users-list-in-state">How to Store the Users List in State</h2>
<p>Now, let's store those users in the state so we can display them on the screen.</p>
<p>Inside the <code>App</code> component, declare a new state with an initial value of an empty array like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [users, setUsers ] = useState([]);
</code></pre>
<p>And call the <code>setUsers</code> function to store the users in the <code>useEffect</code> hook after the API call.</p>
<p>So your <code>App</code> component will look like this now:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FC, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [users, setUsers] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getUsers = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
          <span class="hljs-string">'https://randomuser.me/api/?results=10'</span>
        );
        <span class="hljs-built_in">console</span>.log(data);
        setUsers(data.results);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      }
    };
    getUsers();
  }, []);

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>As you can see here, we're calling the <code>setUsers</code> function with the value of <code>data.results</code>.</p>
<h2 id="heading-how-to-display-the-users-on-the-ui">How to Display the Users on the UI</h2>
<p>Now, let's display the name and email of the individual user on the screen.</p>
<p>If you check the console output, you can see that there is a <code>name</code> property for each object that contains the first and last name of the user. So we can combine them to display the complete name.</p>
<p>Also, we have a direct <code>email</code> property for each user object which we can use to display the email.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/12_required_properties.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Exploring API Response</em></p>
<p>So replace the contents of the <code>App.tsx</code> file with the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FC, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [users, setUsers] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getUsers = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
          <span class="hljs-string">'https://randomuser.me/api/?results=10'</span>
        );
        <span class="hljs-built_in">console</span>.log(data);
        setUsers(data.results);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      }
    };
    getUsers();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
        {users.map(({ login, name, email }) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{login.uuid}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                Name: {name.first} {name.last}
              <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>As you can see, we're using the <a target="_blank" href="https://www.youtube.com/watch?v=ffxvkWmaU7s&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=8">array map method</a> to loop over the <code>users</code> array, and we're using <a target="_blank" href="https://www.youtube.com/watch?v=3JsFklg1WhU&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=20">object destructuring</a> to destructure the <code>login</code>, <code>name</code>, and <code>email</code> properties of individual <code>user</code> objects. Also, we're displaying the name and email of the user as an un-ordered list.</p>
<p>But you will see some TypeScript errors in the file, as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/13_user_errors.png" alt="Image" width="600" height="400" loading="lazy">
<em>User Properties TypeScript Error</em></p>
<p>This is because, as you can see above, by default TypeScript assumes the type of <code>users</code> array to be <code>never[]</code> – so it's not able to find out which properties the <code>users</code> array contains.</p>
<p>This means that we need to specify all of the properties that we're using along with their types.</p>
<p>So now, declare a new interface after the <code>AppProps</code> interface like this:</p>
<pre><code class="lang-javascript">interface Users {
  <span class="hljs-attr">name</span>: {
    <span class="hljs-attr">first</span>: string;
    last: string;
  };
  login: {
    <span class="hljs-attr">uuid</span>: string;
  };
  email: string;
}
</code></pre>
<p>Here, we're specifying that each individual <code>user</code> will be an object with <code>name</code>, <code>login</code>, and <code>email</code> properties. We're also specifying the data type of each property.</p>
<p>As you can see, each <code>user</code> object coming from the API has a lot of other properties like <code>phone</code>, <code>location</code> and others. But we only need to specify those properties that we're using in the code.</p>
<p>Now, change the <code>useState</code> users array declaration from this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [users, setUsers] = useState([]);
</code></pre>
<p>to this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [users, setUsers] = useState&lt;Users[]&gt;([]);
</code></pre>
<p>Here, we're specifying that <code>users</code> is an array of objects of type <code>Users</code> which is the interface we declared.</p>
<p>Now, if you check the <code>App.tsx</code> file, you will see that there are no TypeScript errors.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/14_no_type_error.png" alt="Image" width="600" height="400" loading="lazy">
<em>Fixed Property Types Error</em></p>
<p>And you will be able to see the list of 10 random users displayed on the screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/15_random_users.png" alt="Image" width="600" height="400" loading="lazy">
<em>List Of Random Users Displayed On Screen</em></p>
<p>As you have seen previously, we have declared the <code>Users</code> interface like this:</p>
<pre><code class="lang-javascript">interface Users {
  <span class="hljs-attr">name</span>: {
    <span class="hljs-attr">first</span>: string;
    last: string;
  };
  login: {
    <span class="hljs-attr">uuid</span>: string;
  };
  email: string;
}
</code></pre>
<p>But when you have nested properties, you will see it written like this:</p>
<pre><code class="lang-javascript">interface Name {
  <span class="hljs-attr">first</span>: string;
  last: string;
}

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

interface Users {
  <span class="hljs-attr">name</span>: Name;
  login: Login;
  email: string;
}
</code></pre>
<p>The advantage of declaring separate interfaces for each nested property is that, if you want to use the same structure in any other file, you can just export any of the above interfaces and re-use them other files (instead of re-declaring the same interface again).</p>
<p>So let's export all of the above interfaces as a <a target="_blank" href="https://www.youtube.com/watch?v=_5nxKhP9UOo&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=4">named export</a>. So the code will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> interface Name {
  <span class="hljs-attr">first</span>: string;
  last: string;
}

<span class="hljs-keyword">export</span> interface Login {
  <span class="hljs-attr">uuid</span>: string;
}

<span class="hljs-keyword">export</span> interface Users {
  <span class="hljs-attr">name</span>: Name;
  login: Login;
  email: string;
}
</code></pre>
<p>As I said previously, you can also use type declaration here instead of using the interface, so it will look like this:</p>
<pre><code class="lang-javascript">type Name = {
  <span class="hljs-attr">first</span>: string;
  last: string;
};

type Login = {
  <span class="hljs-attr">uuid</span>: string;
};

type Users = {
  <span class="hljs-attr">name</span>: Name;
  login: Login;
  email: string;
};
</code></pre>
<h2 id="heading-how-to-create-a-separate-user-component">How to Create a Separate User Component</h2>
<p>When we're using an array <code>map</code> method to display something on the screen, it's common to separate out that display part in a different component. This makes it easy to test, and it will also make your component code shorter.</p>
<p>Create a <code>components</code> folder inside the <code>src</code> folder and create a <code>User.tsx</code> file inside it. Then add the following contents inside that file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> User = <span class="hljs-function">(<span class="hljs-params">{ login, name, email }</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">key</span>=<span class="hljs-string">{login.uuid}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Name: {name.first} {name.last}
      <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">hr</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> User;
</code></pre>
<p>If you save the file, you will see the TypeScript errors again.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/16_user_component_props_error.png" alt="Image" width="600" height="400" loading="lazy">
<em>User Component Props Declaration Error</em></p>
<p>So again, we need to specify which props the <code>User</code> component will be receiving. We also need to specify the data type of each of them.</p>
<p>So the updated <code>User.tsx</code> file will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Login, Name } <span class="hljs-keyword">from</span> <span class="hljs-string">'../App'</span>;

interface UserProps {
  <span class="hljs-attr">login</span>: Login;
  name: Name;
  email: string;
}

<span class="hljs-keyword">const</span> User: FC&lt;UserProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ login, name, email }</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">key</span>=<span class="hljs-string">{login.uuid}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Name: {name.first} {name.last}
      <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">hr</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> User;
</code></pre>
<p>As you can see above, we have declared a <code>UserProps</code> interface above and we have specified it for the <code>User</code> component using <code>FC</code>.</p>
<p>Also, note that we're not declaring the data type of the <code>name</code> and <code>login</code> properties. Instead we're using the exported types from the <code>App.tsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Login, Name } <span class="hljs-keyword">from</span> <span class="hljs-string">'../App'</span>;
</code></pre>
<p>That's why it's good to declare separate types for each nested property, so we can reuse them elsewhere.</p>
<p>Now, we can use this <code>User</code> component inside the <code>App.tsx</code> file.</p>
<p>So change the below code:</p>
<pre><code class="lang-javascript">{users.map(<span class="hljs-function">(<span class="hljs-params">{ login, name, email }</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">key</span>=<span class="hljs-string">{login.uuid}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Name: {name.first} {name.last}
      <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  );
})}
</code></pre>
<p>to this code:</p>
<pre><code class="lang-javascript">{users.map(<span class="hljs-function">(<span class="hljs-params">{ login, name, email }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">User</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{login.uuid}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> <span class="hljs-attr">email</span>=<span class="hljs-string">{email}</span> /&gt;</span></span>;
})}
</code></pre>
<p>As you might know, when using the array <code>map</code> method, we need to provide the <code>key</code> for the parent element which is <code>User</code> in our case. So we have added the <code>key</code> prop while using the <code>User</code> component as shown above.</p>
<p>That means we don't need a key inside the <code>User</code> component, so we can remove the <code>key</code> and <code>login</code> prop from the <code>User</code> component.</p>
<p>So the updated <code>User</code> component will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Name } <span class="hljs-keyword">from</span> <span class="hljs-string">'../App'</span>;

interface UserProps {
  <span class="hljs-attr">name</span>: Name;
  email: string;
}

<span class="hljs-keyword">const</span> User: FC&lt;UserProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ name, email }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Name: {name.first} {name.last}
      <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">hr</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> User;
</code></pre>
<p>As you can see, we have removed the <code>login</code> prop from the interface while also destructuring it. The application is still working as before without any issues, as you can see below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/17_working_with_refactor.png" alt="Image" width="600" height="400" loading="lazy">
<em>List Of Random Users Displayed On UI</em></p>
<h2 id="heading-how-to-create-a-separate-file-for-type-declarations">How to Create a Separate File for Type Declarations</h2>
<p>As you can see, the <code>App.tsx</code> file has become quite large because of the interface declarations. It's common to have a separate file just for declaring types.</p>
<p>So create a <code>App.types.ts</code> file inside the <code>src</code> folder and move all the type declarations from the <code>App</code> component to the <code>App.types.ts</code> file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> AppProps {
  title: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Name {
  first: <span class="hljs-built_in">string</span>;
  last: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Login {
  uuid: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Users {
  name: Name;
  login: Login;
  email: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>Note that we're also exporting the <code>AppProps</code> component in the above code.</p>
<p>Now, update the <code>App.tsx</code> file to use these types as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FC, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppProps, Users } <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.types'</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/User'</span>;

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [users, setUsers] = useState&lt;Users[]&gt;([]);

  <span class="hljs-comment">// ...</span>
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>As you can see above, we're importing <code>AppProps</code> and <code>Users</code> from the <code>App.types</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { AppProps, Users } <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.types'</span>;
</code></pre>
<p>And your <code>User.tsx</code> file will look like this now:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FC } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Name } <span class="hljs-keyword">from</span> <span class="hljs-string">'../App.types'</span>;

interface UserProps {
  <span class="hljs-attr">name</span>: Name;
  email: string;
}

<span class="hljs-keyword">const</span> User: FC&lt;UserProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ name, email }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Name: {name.first} {name.last}
      <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>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">hr</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> User;
</code></pre>
<p>As you can see above, we're importing <code>Name</code> from the <code>App.types</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Name } <span class="hljs-keyword">from</span> <span class="hljs-string">'../App.types'</span>;
</code></pre>
<h2 id="heading-how-to-display-a-loading-indicator">How to Display a Loading Indicator</h2>
<p>Whenever you're making an API call to display something, it's always good to display some loading indicator while the API call is going on.</p>
<p>So let's add a new <code>isLoading</code> state inside the <code>App</code> component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>As you can see, we have not mentioned any data type while declaring a state like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState&lt;boolean&gt;(<span class="hljs-literal">false</span>);
</code></pre>
<p>This is because, when we assign any initial value (<code>false</code> in our case), TypeScript automatically infers the type of data we will be storing – which is <code>boolean</code> in our case.</p>
<p>When we declared the <code>users</code> state, it was not clear what we would be storing by just the initial value of an empty array <code>[]</code>. So we needed to mention its type like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [users, setUsers] = useState&lt;Users[]&gt;([]);
</code></pre>
<p>Now, change the <code>useEffect</code> code to the below code:</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> getUsers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      setIsLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">'https://randomuser.me/api/?results=10'</span>
      );
      <span class="hljs-built_in">console</span>.log(data);
      setUsers(data.results);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    } <span class="hljs-keyword">finally</span> {
      setIsLoading(<span class="hljs-literal">false</span>);
    }
  };
  getUsers();
}, []);
</code></pre>
<p>Here, we're calling <code>setIsLoading</code> with a value of <code>true</code> before the API call. Inside the <code>finally</code> block, we're setting it back to <code>false</code>.</p>
<p>The code written inside the <code>finally</code> block will always execute whether it's a success or failure. So whether the API call succeeds or fails, we need to hide the loading message, and we're using the <code>finally</code> block to achieve that.</p>
<p>Now, we can use the <code>isLoading</code> state value to display a loading message on the screen.</p>
<p>After the <code>h1</code> tag and before the <code>ul</code> tag, add the following code:</p>
<pre><code class="lang-javascript">{isLoading &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>}
</code></pre>
<p>Now, if you check the application, you will be able to see the loading message while the list of users is getting loaded.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/18_loading.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Loading Indication Display</em></p>
<p>So this is a better user experience.</p>
<p>But if you keep a closer look at the displayed users, you will see that the users are getting changed once loaded.</p>
<p>So initially we see a set of 10 random users, but then immediately after we see a different set of random users without reloading the page.</p>
<p>This is because we're using React version 18 (which you can verify from the <code>package.json</code> file) and <code>React.StrictMode</code> inside the <code>src/main.tsx</code> file.</p>
<p>And with version 18 of React, when we use <code>React.StrictMode</code>, every <code>useEffect</code> hook executes twice even with no dependency specified.</p>
<p>This only happens in the development environment and not in production when you deploy the application.</p>
<p>Because of this, the API call is made twice. Since the random users API returns a new set of random users every time the API is called, we're setting a different set of users to the <code>users</code> array using the <code>setUsers</code> call inside the <code>useEffect</code> hook.</p>
<p>This is the reason we see users getting changed without refreshing the page.</p>
<p>If you don't want this behaviour during development, you can remove the <code>React.StrictMode</code> from the <code>main.tsx</code> file.</p>
<p>So change the below code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.tsx'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)!).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> <span class="hljs-attr">title</span>=<span class="hljs-string">'TypeScript Demo'</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>to this code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.tsx'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)!).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> <span class="hljs-attr">title</span>=<span class="hljs-string">'TypeScript Demo'</span> /&gt;</span></span>
);
</code></pre>
<p>Now, if you check the application, you will see that the list of users is not getting changed once it's loaded.</p>
<h2 id="heading-how-to-load-users-on-button-click">How to Load Users on Button Click</h2>
<p>Now, instead of making the API call on page load, let's add a "show users" button and we will make the API call when we click on that button.</p>
<p>So after the <code>h1</code> tag, add a new button as shown below:</p>
<pre><code class="lang-javascript">&lt;button onClick={handleClick}&gt;Show Users&lt;/button&gt;
</code></pre>
<p>Now, add the <code>handleClick</code> method inside the <code>App</code> component and move all the code from the <code>getUsers</code> function to the <code>handleClick</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleClick = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    setIsLoading(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://randomuser.me/api/?results=10'</span>);
    <span class="hljs-built_in">console</span>.log(data);
    setUsers(data.results);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  } <span class="hljs-keyword">finally</span> {
    setIsLoading(<span class="hljs-literal">false</span>);
  }
};
</code></pre>
<p>Now, you can remove or comment out the <code>useEffect</code> hook, as it's no longer needed.</p>
<p>Your updated <code>App.tsx</code> file will look like this now:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FC, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { AppProps, Users } <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.types'</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/User'</span>;

<span class="hljs-keyword">const</span> App: FC&lt;AppProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [users, setUsers] = useState&lt;Users[]&gt;([]);
  <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState&lt;boolean&gt;(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      setIsLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://randomuser.me/api/?results=10'</span>);
      <span class="hljs-built_in">console</span>.log(data);
      setUsers(data.results);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    } <span class="hljs-keyword">finally</span> {
      setIsLoading(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Show Users <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      {isLoading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
        {users.map(({ login, name, email }) =&gt; {
          return <span class="hljs-tag">&lt;<span class="hljs-name">User</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{login.uuid}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> <span class="hljs-attr">email</span>=<span class="hljs-string">{email}</span> /&gt;</span>;
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now, if you check the application, you will see that users are loaded only when clicking on the show users button. We also see the loading message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/19_load_on_click.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Users Loaded On Button Click</em></p>
<h2 id="heading-how-to-handle-the-change-event">How to Handle the Change Event</h2>
<p>Now, let's add an input field. When we type anything in that input field, we will display the entered text below that input field.</p>
<p>Add an input field after the button like this:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={handleChange} /&gt;
</code></pre>
<p>And declare a new state to store the entered value like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">''</span>);
</code></pre>
<p>Now, add a <code>handleChange</code> method inside the <code>App</code> component like this:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  setUsername(event.target.value);
};
</code></pre>
<p>However, you will see that we're getting a TypeScript error for the event parameter.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/20_event_type.png" alt="Image" width="600" height="400" loading="lazy">
<em>Event Type Missing TypeScript Error</em></p>
<p>With TypeScript, we always need to specify the type of each and every function parameter.</p>
<p>Here, TypeScript is not able to identify the type of the <code>event</code> parameter.</p>
<p>To find out the type of <code>event</code> parameter, we can change the below code:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={handleChange} /&gt;
</code></pre>
<p>to this code:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {}} /&gt;
</code></pre>
<p>Here, we're using an inline function, because when using inline function, the correct type is automatically passed to the function parameter so we don't need to specify it.</p>
<p>If you mouse over the <code>event</code> parameter, you will be able to see the exact type of event that we can use in our <code>handleChange</code> function as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/21_change_event_type.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Identifying TypeScript Event Type Using Inline Function</em></p>
<p>Now, you can revert the below code:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {}} /&gt;
</code></pre>
<p>to this code:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={handleChange} /&gt;
</code></pre>
<p>Now, let's display the value of the <code>username</code> state variable below the input field:</p>
<pre><code class="lang-javascript">&lt;input type=<span class="hljs-string">'text'</span> onChange={handleChange} /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{username}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>If you check the application now, you will be able to see the entered text displayed below the input field.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/22_username.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying User Entered Text On UI</em></p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for Reading</strong></h2>
<p>That's it for this tutorial. I hope you learned a lot from it.</p>
<p>Want to watch the video version of this tutorial? You can check out <a target="_blank" href="https://www.youtube.com/watch?v=KmYoJmZs3sY">this video.</a></p>
<p>You can find the complete source code for this application in <a target="_blank" href="https://github.com/myogeshchavan97/react-typescript-demo">this repository</a>.</p>
<p>If you want to master JavaScript, ES6+, React, and Node.js with easy-to-understand content, check out my <a target="_blank" href="https://www.youtube.com/@codingmastery_dev/">YouTube channel</a>. Don't forget to subscribe.</p>
<p>Want to stay up to date with regular content on JavaScript, React, and Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
<p><a target="_blank" href="https://courses.yogeshchavan.dev/build-expense-manager-app-using-react-and-typescript"><img src="https://www.freecodecamp.org/news/content/images/2023/11/expense_manager_app_banner.png" alt="Learn To Build Expense Manager App Using React And TypeScript" width="600" height="400" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Avoid Breaking Your React Application in Production ]]>
                </title>
                <description>
                    <![CDATA[ Did you know that your React application that's deployed to production can crash any time because of unhandled errors? Thankfully, React Error Boundaries are here to save the day! Whenever any type of error happens during the rendering of a component... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-avoid-breaking-your-react-app-in-production/</link>
                <guid isPermaLink="false">66bc550573c9920bb20c0e55</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Tue, 17 Oct 2023 23:13:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/cover_image.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Did you know that your React application that's deployed to production can crash any time because of unhandled errors?</p>
<p>Thankfully, React Error Boundaries are here to save the day!</p>
<p>Whenever any type of error happens during the rendering of a component or in lifecycle methods, React displays a blank page without showing any error message.</p>
<p>And getting a blank page on the production site is definitely not a good user experience.</p>
<p>So React Error Boundaries provide a powerful mechanism to catch and gracefully handle errors that occur during the rendering lifecycle of your components.</p>
<p>Want to watch the video version of this tutorial? You can check out the video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/gVj84413hVg" 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-what-are-error-boundaries-in-react">What are Error Boundaries in React?</h2>
<p>Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.</p>
<p>Error boundaries catch errors during rendering, in lifecycle methods, and in the whole tree below them.</p>
<h2 id="heading-why-do-we-need-error-boundaries">Why Do We Need Error Boundaries?</h2>
<p>In your React application, there might be some edge cases that you might not have handled. Because of that you might get an error in production, and you will see a blank screen.</p>
<p>This is not a good user experience, so adding an error boundary helps to mitigate this issue.</p>
<p>To better understand it, you can clone <a target="_blank" href="https://github.com/myogeshchavan97/react-router-6-demo">this GitHub Repository</a> which I have created in <a target="_blank" href="https://www.youtube.com/watch?v=b_YbEp8BLMQ">this video</a>.</p>
<p>Once cloned, you can execute the <code>npm install</code> command from the project folder to install all the project dependencies and then execute the <code>npm run dev</code> command to start the application.</p>
<p>Now, you can access the application, by visiting <a target="_blank" href="http://localhost:5173/">http://localhost:5173/</a>.</p>
<p>You will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/1_initial_screen.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initial Screen on the Example App</em></p>
<h2 id="heading-how-the-application-works">How the Application Works</h2>
<p>Now, if you click on any of the courses, you will see the course details page.</p>
<p>Let's say you click on the <code>Learn Food Recipes</code> course. Then you will see the screen as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/2_details_screen.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Course Details Page</em></p>
<p>If you check the code, you will see that the details page content is coming from the <code>CourseDetails</code> component as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/3_course_details.png" alt="Image" width="600" height="400" loading="lazy">
<em>Course Details Component Code</em></p>
<p>As you can see above, we have static <code>courses</code> data imported from the <code>utils/data</code> file at line number 3. On line number 8, we're using the <a target="_blank" href="https://www.youtube.com/watch?v=eCTT9G7RVg4&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=9">array find method</a> to check if the page URL matches any of the course URLs.</p>
<p>If we find a match, then the <code>find</code> method will return the found course which we're storing in the <code>selectedCourse</code> variable.</p>
<p>And if there is no matching course, the <code>find</code> method will return <code>undefined</code> as the value.</p>
<p>So on line number 11, we're redirecting the user to the home page using the <code>Navigate</code> component of <a target="_blank" href="https://courses.yogeshchavan.dev/react-router-6">react-router-dom</a> library if there is no matching course found.</p>
<p>To verify that, you can add some extra characters to the details page URL, and you will see that you're redirected to the home page as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/4_redirection.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Automatic Redirection From Details Page</em></p>
<h2 id="heading-how-to-generate-an-error-in-the-application">How to Generate an Error in the Application</h2>
<p>Instead, let's say we don't have the condition of line number 11 for redirection, and also we don't have the fallback of an empty object <code>{}</code> specified.</p>
<p>So instead of this code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> CourseDetails = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { pathname } = useLocation();
  <span class="hljs-keyword">const</span> selectedCourse = courses.find(<span class="hljs-function">(<span class="hljs-params">course</span>) =&gt;</span> course.url === pathname);

  <span class="hljs-keyword">if</span> (!selectedCourse) {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navigate</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/'</span> /&gt;</span></span>;
  }
  <span class="hljs-keyword">const</span> { title, duration, enrolledCount, courseImage, author } =
    selectedCourse || {};
  ...
}
</code></pre>
<p>we have code like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> CourseDetails = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { pathname } = useLocation();
  <span class="hljs-keyword">const</span> selectedCourse = courses.find(<span class="hljs-function">(<span class="hljs-params">course</span>) =&gt;</span> course.url === pathname);

  <span class="hljs-keyword">const</span> { title, duration, enrolledCount, courseImage, author } =
    selectedCourse;
  ...
}
</code></pre>
<p>Now, with this code, if we don't find a course with a matching course URL, then the array <code>find</code> method will return <code>undefined</code> as the value.</p>
<p>So when we destructure the <code>title</code>, <code>duration</code> and other properties from the <code>selectedCourse</code> variable, JavaScript will throw an error.</p>
<p>To see it in action, open Chrome DevTools, and go to any of the course's details page, and add some random characters in the URL.</p>
<p>When you press the enter key, you will see a blank screen with an error in the console, as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/5_error_screen.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Console Error With Broken Application</em></p>
<p>So as you can see, the application is broken and nothing is displayed on the screen. As I mentioned above, getting a blank screen without any text is not a good user experience. The user will not know what happened and what to do in such situations.</p>
<p>The error is happening because we're trying to destructure properties from <code>undefined</code>.</p>
<p>You can only destructure properties from objects and not <code>undefined</code>.</p>
<p>Forgetting to provide a default fallback of an empty object <code>{}</code> is a common thing when you have a large application.</p>
<p>So to avoid such scenarios of getting a black page, we can use the popular <a target="_blank" href="https://www.npmjs.com/package/react-error-boundary">react-error-boundary</a> npm library.</p>
<h2 id="heading-how-to-use-the-react-error-boundary-library">How to Use the react-error-boundary Library</h2>
<p>To use this library, let's first install it by executing the following command from the terminal from inside the project folder:</p>
<pre><code class="lang-js">npm install react-error-boundary
</code></pre>
<p>Once installed, restart the application by executing the <code>npm run dev</code> command.</p>
<p>Now, we can wrap our entire <code>App</code> component inside the <code>ErrorBoundary</code> component imported from the <code>react-error-boundary</code> library.</p>
<p>So open <code>src/main.jsx</code> file and change the below code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.scss'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>to this code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> { ErrorBoundary } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-error-boundary'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.scss'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">p</span>&gt;</span>Something went wrong. Try again later.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>In the above code, we have wrapped the <code>App</code> component in between the opening and closing <code>ErrorBoundary</code> component and we have also imported the <code>ErrorBoundary</code> component from <code>react-error-boundary</code>.</p>
<p>For the <code>ErrorBoundary</code> component, we're providing the <code>fallback</code> prop with the text to be displayed in case any error occurs.</p>
<p>So now with this change, if you try to navigate to some invalid details page URL, you will see the fallback text displayed as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/6_fallback_error.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying Fallback Error Message</em></p>
<p>But just displaying this simple text is not veru useful. So what else can we do?</p>
<h2 id="heading-how-to-display-a-proper-error-page">How to Display a Proper Error Page</h2>
<p>So instead of using the <code>fallback</code> prop, we will use <code>FallbackComponent</code> prop. As a value for the prop, we can provide either a class component or a functional component.</p>
<p>So inside the <code>components</code> folder create a new <code>error-page</code> folder. Inside it create an <code>ErrorPage.jsx</code> file with the following content:</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> NotFoundImage <span class="hljs-keyword">from</span> <span class="hljs-string">'../../assets/writer.svg'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./error_page.scss'</span>;

<span class="hljs-keyword">const</span> ErrorPage = <span class="hljs-function">(<span class="hljs-params">{ error }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error occured'</span>, error);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-page'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{NotFoundImage}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'Page not found'</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-msg'</span>&gt;</span>
        Something went wrong. Try clicking the refresh page button to reload the
        application.{' '}
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span>&gt;</span>
          Refresh page
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ErrorPage;
</code></pre>
<p>You can download the <code>writer.svg</code> image which is referenced in the above code from <a target="_blank" href="https://github.com/myogeshchavan97/react-error-boundary-demo/blob/master/src/assets/writer.svg">this repository</a> and place it inside <code>src/assets</code> folder.</p>
<p>Also, create <code>error_page.scss</code> file inside the <code>error-page</code> folder and add the following content inside it:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.error-page</span> {
  <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">margin-top</span>: <span class="hljs-number">5rem</span>;
  <span class="hljs-attribute">max-height</span>: <span class="hljs-number">100vh</span>;

  img {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
    <span class="hljs-attribute">height</span>: auto;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1rem</span>;
  }
  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">130%</span>;
  }
  <span class="hljs-selector-class">.error-msg</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">font-weight</span>: bold;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">1rem</span>;
  }
  <span class="hljs-selector-class">.btn</span> {
    <span class="hljs-attribute">width</span>: fit-content;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span> <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#bd1d3d</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
    <span class="hljs-attribute">letter-spacing</span>: <span class="hljs-number">1px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">cursor</span>: pointer;
  }
}
</code></pre>
<p>Now, open the <code>src/main.jsx</code> file and replace it with the following content:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> { ErrorBoundary } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-error-boundary'</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> ErrorPage <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/error-page/ErrorPage'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.scss'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span> <span class="hljs-attr">FallbackComponent</span>=<span class="hljs-string">{ErrorPage}</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">ErrorBoundary</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>In the above code, we have used <code>FallbackComponent</code> prop instead of <code>fallback</code> prop and we added the <code>ErrorPage</code> component as its value.</p>
<p>Also, note that we have added an import statement for the <code>ErrorPage</code> component.</p>
<p>So now, If you try going to some invalid details page URL, you will see a nicely designed error page with a <code>Refresh page</code> button displayed on the screen as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/7_nice_error_page.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying Nice Error Page</em></p>
<p>So now with the error boundary added, the end user no longer sees a blank page when something goes wrong.</p>
<p>So even if there is an error in the console, we no longer see a blank page.</p>
<p>This is a great improvement to the application.</p>
<p>Note that the error page is displayed only if rendering fails like a blank page is displayed.</p>
<p>And when the error page is displayed, we automatically get the <code>error</code> prop inside the <code>ErrorPage</code> component which we have created inside the <code>ErrorPage.jsx</code> file as you can see below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> NotFoundImage <span class="hljs-keyword">from</span> <span class="hljs-string">'../../assets/writer.svg'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./error_page.scss'</span>;

<span class="hljs-keyword">const</span> ErrorPage = <span class="hljs-function">(<span class="hljs-params">{ error }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error occured'</span>, error);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-page'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{NotFoundImage}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'Page not found'</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-msg'</span>&gt;</span>
        Something went wrong. Try clicking the refresh page button to reload the
        application.{' '}
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span>&gt;</span>
          Refresh page
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ErrorPage;
</code></pre>
<p>In the above code, we're just logging the <code>error</code> prop value to the console.</p>
<p>The <code>ErrorBoundary</code> component also accepts an <code>onReset</code> function prop where we can write code to redirect the user to the home page.</p>
<p>And with the <code>onReset</code> prop added to the <code>ErrorBoundary</code> component, we get access to the <code>resetErrorBoundary</code> prop inside the <code>ErrorPage</code> component.</p>
<p>So change the <code>ErrorPage</code> component to the below code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ErrorPage = <span class="hljs-function">(<span class="hljs-params">{ error, resetErrorBoundary }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error occured'</span>, error);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-page'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{NotFoundImage}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'Page not found'</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'error-msg'</span>&gt;</span>
        Something went wrong. Try clicking the refresh page button to reload the
        application.{' '}
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'btn'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{resetErrorBoundary}</span>&gt;</span>
          Refresh page
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>In the above code, we're destructuring the <code>resetErrorBoundary</code> prop which we will be using for the <code>onClick</code> handler of <code>Refresh page</code> button.</p>
<p>Now, change the <code>ErrorBoundary</code> component code from <code>src/main.jsx</code> file to the below code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> { ErrorBoundary } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-error-boundary'</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> ErrorPage <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/error-page/ErrorPage'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.scss'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span>
      <span class="hljs-attr">FallbackComponent</span>=<span class="hljs-string">{ErrorPage}</span>
      <span class="hljs-attr">onReset</span>=<span class="hljs-string">{()</span> =&gt;</span> (location.href = '/')}
    &gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>So when we click on the <code>Refresh page</code> button, the <code>resetErrorBoundary</code> function will be called and it will reset all the errors and code from the <code>onReset</code> function which we have added to the <code>src/main.jsx</code> file will be executed which will redirect the user to the home page.</p>
<p>You can see it in action below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/8_reset_errors.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Resetting Errors With Redirection</em></p>
<p>So as you can see above, with the error boundary added, we're clearly able to see the proper error page with <code>Refresh page</code> button. Once we click on the button, we're redirected to the home page, and all the errors are cleared from the console.</p>
<p>This is a great user experience for the end user instead of getting a blank page.</p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for Reading</strong></h2>
<p>That's it for this tutorial. I hope you learned a lot from it.</p>
<p>Want to watch the video version of this tutorial? You can check out <a target="_blank" href="https://www.youtube.com/watch?v=gVj84413hVg">this video.</a></p>
<p>You can find the complete source code for this application in <a target="_blank" href="https://github.com/myogeshchavan97/react-error-boundary-demo">this repository</a>.</p>
<p>If you want to master JavaScript, ES6+, React, and Node.js with easy-to-understand content, check out my <a target="_blank" href="https://www.youtube.com/@codingmastery_dev/">YouTube channel</a>. Don't forget to subscribe.</p>
<p>Want to stay up to date with regular content on JavaScript, React, and Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Image Search App Using React – An In-Depth Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will build step-by-step a beautiful Unsplash Image Search App with pagination using React. By building this app, you will learn: How to build an application using Unsplash API in React How to make API Calls in different scenarios... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-image-search-app-using-react/</link>
                <guid isPermaLink="false">66bc550bda80a491ea5a5f3b</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Sat, 30 Sep 2023 11:30:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/unsplash_image_search_app.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will build step-by-step a beautiful Unsplash Image Search App with pagination using React.</p>
<p>By building this app, you will learn:</p>
<ul>
<li>How to build an application using Unsplash API in React</li>
<li>How to make API Calls in different scenarios</li>
<li>How to use <code>useCallback</code> hook to avoid function re-creation</li>
<li>How to use ESLint to fix application issues</li>
<li>How to Implement Pagination in React</li>
</ul>
<p>and much more...</p>
<p>Want to watch the video version of this tutorial? You can check out the video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/0YoT44j3Jg4" 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-initial-project-setup">Initial Project Setup</h2>
<p>We will use <a target="_blank" href="https://vitejs.dev/">Vite</a> to create a project which is a popular alternative to <code>create-react-app</code>.</p>
<p>Execute the following command to create a vite project:</p>
<pre><code class="lang-js">npm create vite
</code></pre>
<p>Once executed, you will be asked some questions.</p>
<p>For the project name, enter <code>unsplash_image_search</code>.</p>
<p>For framework, select <code>React</code> and for variant select <code>JavaScript</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/2_create_project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating Project Using Vite</em></p>
<p>Once the project is created, open the project in VS Code and execute the following commands from the terminal:</p>
<pre><code class="lang-js">cd unsplash_image_search
npm install
npm run dev
</code></pre>
<p>Access the application by navigating to <a target="_blank" href="http://127.0.0.1:5173/">http://127.0.0.1:5173/</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/3_project_started.png" alt="Image" width="600" height="400" loading="lazy">
<em>Application Started</em></p>
<p>You will see the default application screen as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/1_app_screen.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initial Screen</em></p>
<p>Next, delete the <code>App.css</code> file and replace the contents of the <code>App.jsx</code> file with the following content:</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">'./index.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>&gt;</span>Welcome to Unsplash Image Search<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, open the <code>index.css</code> file and add the contents from <a target="_blank" href="https://github.com/myogeshchavan97/unsplash_image_search/blob/master/src/index.css">this GitHub repo</a> to it.</p>
<p>Let's install <a target="_blank" href="https://getbootstrap.com/">Bootstrap</a> and <a target="_blank" href="https://react-bootstrap.netlify.app/">react-bootstrap</a> npm packages by executing the following command:</p>
<pre><code class="lang-js">npm install bootstrap react-bootstrap
</code></pre>
<p>Open the <code>main.jsx</code> file and add the following line of code on the first line, to add the base bootstrap CSS file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
</code></pre>
<p>The complete <code>main.jsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">'bootstrap/dist/css/bootstrap.min.css'</span>;
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.jsx'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>Now, restart the application by executing <code>npm run dev</code> command.</p>
<p>You will see the welcome message displayed on the screen as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/4_initial_screen.png" alt="Image" width="600" height="400" loading="lazy">
<em>Welcome Screen</em></p>
<h2 id="heading-how-to-add-search-input">How to Add Search Input</h2>
<p>Now, replace the contents of <code>App.jsx</code> file with the following content:</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> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.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">'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">'title'</span>&gt;</span>Image Search<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">'search-section'</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">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</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>&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>Here, we're displaying the title of <code>Image search</code> inside a <code>container</code> class, which is a Bootstrap class, to add some margin to the left and right of the page.</p>
<p>Then we added a <a target="_blank" href="https://react-bootstrap.netlify.app/docs/forms/overview/">form</a> with a type of <code>search</code>.</p>
<p>If you check the application, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/5_searchbox.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initial Search UI</em></p>
<p>Now, we need to store the value entered by the user somewhere in the component.</p>
<p>As we will have only one input field on the page, we will use the <a target="_blank" href="https://react.dev/reference/react/useRef">useRef</a> hook instead of the <code>useState</code> hook.</p>
<p>Using the <code>useRef</code> hook does not re-render the component when its value changes, which is good for performance improvement. On the other hand, changing state re-renders the component, so all of the child components will also re-render.</p>
<p>Inside the <code>App.jsx</code> file, declare the <code>useRef</code> hook as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);
</code></pre>
<p>Don't forget to add import for <code>useRef</code> hook at the top of the file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</code></pre>
<p>Also, add a <code>ref</code> prop for the search input, like this:</p>
<pre><code class="lang-jsx">&lt;Form.Control
   type=<span class="hljs-string">'search'</span>
   placeholder=<span class="hljs-string">'Type something to search...'</span>
   className=<span class="hljs-string">'search-input'</span>
   ref={searchInput}
/&gt;
</code></pre>
<p>Your complete <code>App.jsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">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">'title'</span>&gt;</span>Image Search<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">'search-section'</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">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</span>
            <span class="hljs-attr">ref</span>=<span class="hljs-string">{searchInput}</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>&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>
<h2 id="heading-how-to-handle-the-form-submit-action">How to Handle the Form Submit Action</h2>
<p>When we enter any search term in the search box and press the enter key, we want to add the search functionality.</p>
<p>To do so, add an <code>onSubmit</code> handler to the <code>Form</code> tag and create a <code>handleSearch</code> method. And assign it to the <code>onSubmit</code> prop like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'submitted'</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">'title'</span>&gt;</span>Image Search<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">'search-section'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearch}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</span>
            <span class="hljs-attr">ref</span>=<span class="hljs-string">{searchInput}</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>&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>Here, we have added <code>&lt;Form onSubmit={handleSearch}&gt;</code> and inside the <code>handleSearch</code> method we used the <code>event.preventDefault</code> method.</p>
<p>Once the form is submitted by pressing the enter key in the search box, the page will not refresh and a submitted text will be displayed in the console as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/6_submitted.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Form Submission Action</em></p>
<p>Now, instead of printing "submitted", we can print the value entered by the user using <code>searchInput.current.value</code>. </p>
<p>Here, <code>searchInput</code> is the <code>ref</code> and <code>searchInput.current</code> will be the actual search box input. Also, using <code>searchInput.current.value</code> will give the actual value entered by the user.</p>
<p>So, replace the <code>handleSearch</code> method with the following code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  event.preventDefault();
  <span class="hljs-built_in">console</span>.log(searchInput.current.value);
};
</code></pre>
<p>And now you will see the entered value displayed in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/7_searchterm.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying Entered Search Term Value In Console</em></p>
<h2 id="heading-how-to-add-quick-search-options">How to Add Quick Search Options</h2>
<p>Now, let's add action buttons with a class of <code>filters</code> for a quick search just below the <code>search-section</code> div:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'container'</span>&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">'title'</span>&gt;</span>Image 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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'search-section'</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">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'filters'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Nature<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>Birds<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>Cats<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>Shoes<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>
&lt;/div&gt;
</code></pre>
<p>Now, the application will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/8_buttons_added.png" alt="Image" width="600" height="400" loading="lazy">
<em>Quick Search Options Added</em></p>
<p>When we click on any of the displayed buttons, we can display the clicked button value in the input search box, so we can use it for searching the images.</p>
<p>Change the <code>filters</code> div to the below code:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'filters'</span>&gt;
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('nature')}&gt;Nature<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">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('birds')}&gt;Birds<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">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('cats')}&gt;Cats<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">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('shoes')}&gt;Shoes<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>In the above code, when you click on any option, we're passing the selected option to the <code>handleSelection</code> method.</p>
<p>Now, add a new <code>handleSelection</code> method inside the <code>App</code> component as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
  searchInput.current.value = selection;
};
</code></pre>
<p>Your complete <code>App.jsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(searchInput.current.value);
  };

  <span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
    searchInput.current.value = selection;
  };

  <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">'title'</span>&gt;</span>Image Search<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">'search-section'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearch}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</span>
            <span class="hljs-attr">ref</span>=<span class="hljs-string">{searchInput}</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>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'filters'</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> handleSelection('nature')}&gt;Nature<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('birds')}&gt;Birds<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('cats')}&gt;Cats<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('shoes')}&gt;Shoes<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><img src="https://www.freecodecamp.org/news/content/images/2023/09/9_selection.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying Selection Option In the Search Box</em></p>
<h2 id="heading-how-to-get-access-to-the-unsplash-api">How to Get Access to the Unsplash API</h2>
<p>Now, to implement the image search, we need to get the API key from <a target="_blank" href="https://unsplash.com/">Unsplash Website</a>.</p>
<p>Navigate to <a target="_blank" href="https://unsplash.com/developers">this URL</a>, and click on  the "Register as a developer" button displayed at the top right corner of the page. Create your account by entering all the necessary details.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/10_register_as_developer.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once registered, you will be redirected to <a target="_blank" href="https://unsplash.com/oauth/applications">this page</a> as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/11_applications_page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Registering New Application With Unsplash API</em></p>
<p>Click on the <code>New Application</code> button. On the next screen:</p>
<ul>
<li>Check all the checkboxes and click on <code>Accept Terms</code> button</li>
<li>Enter values for <code>Application name</code> and <code>Description</code> and click <code>Create application</code> button</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/13_create_application.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Creating New Application With Unsplash API</em></p>
<p>Scroll down a bit and copy the <code>Access Key</code> which is displayed on the screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/14_access_key_copy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Getting Access Key From Unsplash API</em></p>
<p>Next, create a new <code>.env</code> file in your project and add a new environment variable with the name <code>VITE_API_KEY</code>. Also, assign the copied value of the API key to it:</p>
<pre><code class="lang-jsx">VITE_API_KEY=A4UiJ5OIwL_4ccbCAE1ZXw3EgoNRotMbdNe12qtKHzM
</code></pre>
<p>Make sure to start the variable name with <code>VITE_</code> so it will be accessible in the application.</p>
<p>Your application folder structure will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/15_api_key.png" alt="Image" width="600" height="400" loading="lazy">
<em>File Structure With .env File</em></p>
<p>Also, make sure to add <code>.env</code> in the <code>.gitignore</code> file so the file will not be pushed to GitHub when changes are pushed to GitHub.</p>
<p>Now, navigate to <a target="_blank" href="https://unsplash.com/documentation">Unsplash Documentation</a> and click on the <code>Search photos by keyword</code> section. And copy the following base API URL: <code>https://api.unsplash.com/search/photos</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/16_base_api_url.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Search Images API Documentation Page</em></p>
<p>Now, open <code>App.jsx</code> file and paste that copied URL as <code>API_URL</code> after all import statements, like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> API_URL = <span class="hljs-string">'https://api.unsplash.com/search/photos'</span>;
</code></pre>
<p>According to the documentation, the search photos API with the above URL accepts the <code>query</code>, <code>page</code> and <code>per_page</code> as the query parameters. Just note this, as we will be using it soon.</p>
<h2 id="heading-how-to-make-an-api-call-to-the-unsplash-api">How to Make an API Call to the Unsplash API</h2>
<p>To make an API call, let's first install the <code>axios</code> npm library by executing the following command from the project folder:</p>
<pre><code class="lang-js">npm install axios
</code></pre>
<p>Once installed, start the application again by executing the <code>npm run dev</code> command.</p>
<p>Next, declare a new constant just below the <code>API_URL</code> constant:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> IMAGES_PER_PAGE = <span class="hljs-number">20</span>;
</code></pre>
<p>Here, we're specifying to display <code>20</code> images per page when we will implement pagination. You can change it to any value you want.</p>
<p>Add a new <code>fetchImages</code> function inside the <code>App</code> component like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
      <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
        searchInput.current.value
      }</span>&amp;page=1&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
        <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
      }</span>`</span>
    );
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};
</code></pre>
<p>Here, we have defined a <code>fetchImages</code> function which is declared <code>async</code> so we can use <code>await</code> inside it.</p>
<p>If you're not aware of promises and async/await, I highly recommend checking out <a target="_blank" href="https://www.freecodecamp.org/news/javascript-promises-async-await-and-promise-methods/">this article</a>.</p>
<p>Then, inside the <code>fetchImages</code> function, we're making a GET API call using axios to the URL which we have stored in the <code>API_URL</code> constant: <code>https://api.unsplash.com/search/photos</code>.</p>
<p>For the API URL, we're passing the following query parameters using <a target="_blank" href="https://bit.ly/3rtiQ9y">template literal syntax</a>:</p>
<ul>
<li><code>query</code> with the value of user entered or quick search option value</li>
<li><code>page</code> with a value of <code>1</code> to get the first page data</li>
<li><code>per_page</code> with the value of <code>20</code> which is defined in the constant <code>IMAGES_PER_PAGE</code></li>
<li><code>client_id</code> with the value of the API key from the <code>.env</code> file.</li>
</ul>
<p>As we're using <a target="_blank" href="https://vitejs.dev/">Vite</a>, to access environment variables from the <code>.env</code> file, we need to use <code>import.meta.env.VITE_API_KEY</code>.</p>
<p>Here, <code>VITE_API_KEY</code> is the environment variable we declared in the <code>.env</code> file.</p>
<p>Also, import the <code>axios</code> library at the top of the file like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> axios;
</code></pre>
<p>The updated <code>App.jsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">const</span> API_URL = <span class="hljs-string">'https://api.unsplash.com/search/photos'</span>;
<span class="hljs-keyword">const</span> IMAGES_PER_PAGE = <span class="hljs-number">20</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> fetchImages = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=1&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  };

  <span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(searchInput.current.value);
  };

  <span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
    searchInput.current.value = selection;
    fetchImages();
  };

  <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">'title'</span>&gt;</span>Image Search<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">'search-section'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearch}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</span>
            <span class="hljs-attr">ref</span>=<span class="hljs-string">{searchInput}</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>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'filters'</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> handleSelection('nature')}&gt;Nature<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('birds')}&gt;Birds<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('cats')}&gt;Cats<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('shoes')}&gt;Shoes<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>If you check the application, you will see that, on every click of the quick search option, the API call is made to the Unsplash API, and we get the data for the selected option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/17_api_result.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Making API Call When Clicked Quick Search Option</em></p>
<p>To make an API call when we enter the search text and press enter key, we need to call the <code>fetchImages</code> function from the <code>handleSearch</code> function also.</p>
<p>To do this, add a call to <code>fetchImages</code> function inside the <code>handleSearch</code> function as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(searchInput.current.value);
    fetchImages();
};
</code></pre>
<p>Now, you will be able to see the API call made in the network tab when we enter a search text and press enter key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/18_search_result.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Making API Call When Entered Text In The Searchbox</em></p>
<h2 id="heading-how-to-store-api-data-using-state">How to Store API Data Using State</h2>
<p>Now, let's display the images coming from the API on the screen.</p>
<p>To display them on the screen, we first need to store the data coming from the API.</p>
<p>If you see the structure of the API response, you will see as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/19_response.png" alt="Image" width="600" height="400" loading="lazy">
<em>API Response</em></p>
<p>So, declare two states in the <code>App.jsx</code> file: one for storing response images which are coming in the <code>results</code> property, and another for storing <code>total_pages</code> so we can implement the pagination.</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> searchInput = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [images, setImages] = useState([]);
  <span class="hljs-keyword">const</span> [totalPages, setTotalPages] = useState(<span class="hljs-number">0</span>);
  ....
}
</code></pre>
<p>And update the <code>fetchImages</code> function to store the <code>data.results</code> using <code>setImages</code> and total pages using <code>setTotalPages</code> function:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=1&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
      setImages(data.results);
      setTotalPages(data.total_pages);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  };
</code></pre>
<h2 id="heading-how-to-display-images-on-screen">How to Display Images On Screen</h2>
<p>Now, let's display the images that we have stored in the <code>images</code> state variable.</p>
<p>If you expand the individual image response of the API, you can see the <code>id</code>, <code>alt_description</code>, <code>urls</code> properties which we can use to display individual images.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/20_api_response.gif" alt="Image" width="600" height="400" loading="lazy">
<em>API Response Properties</em></p>
<p>So, just after the <code>filters</code> div, add another div for displaying images like this:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'filters'</span>&gt;
  ...
&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">'images'</span>&gt;</span>
  {images.map((image) =&gt; {
    return (
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
        <span class="hljs-attr">key</span>=<span class="hljs-string">{image.id}</span>
        <span class="hljs-attr">src</span>=<span class="hljs-string">{image.urls.small}</span>
        <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.alt_description}</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">'image'</span>
      /&gt;</span>
    );
  })}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Here, we're displaying the <code>small</code> version of the image from the <code>urls</code> property of the individual image.</p>
<p>We can simplify the above code further. Inside the array <code>map</code> method, instead of using a curly bracket with a <code>return</code> keyword, we can re-write it like this:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'filters'</span>&gt;
  ...
&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">'images'</span>&gt;</span>
{images.map((image) =&gt; (
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
    <span class="hljs-attr">key</span>=<span class="hljs-string">{image.id}</span>
    <span class="hljs-attr">src</span>=<span class="hljs-string">{image.urls.small}</span>
    <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.alt_description}</span>
    <span class="hljs-attr">className</span>=<span class="hljs-string">'image'</span>
  /&gt;</span>
))}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Here, we're implicitly returning the JSX from the array <code>map</code> method by adding a round bracket around the JSX.</p>
<p>Now, If you search for any text, you will see the images displayed correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/21_displayed_images.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displayed Images When Clicked On Quick Search Icon</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/22_displayed_images.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displayed Images When Clicked On Quick Search Icon</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/23_displayed_images.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displayed Images After Entering Search Term</em></p>
<h2 id="heading-how-to-implement-pagination">How to Implement Pagination</h2>
<p>Now, we will add previous and next buttons to see different sets of images.</p>
<p>So, first declare a new state in the <code>App</code> component as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">1</span>);
</code></pre>
<p>Inside the <code>fetchImages</code> function, change <code>page=1</code> to <code>page=${page}</code> so when we change the value of the <code>page</code>, images for the selected <code>page</code> will be loaded.</p>
<p>Add a new div with a class of <code>buttons</code> just below the <code>images</code> div as shown below:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'images'</span>&gt;
  ...
&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">'buttons'</span>&gt;</span>
  {page &gt; 1 &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>&gt;</span>Previous<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>}
  {page <span class="hljs-tag">&lt; <span class="hljs-attr">totalPages</span> &amp;&amp; &lt;<span class="hljs-attr">Button</span>&gt;</span>Next<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>In the above code, we show the <code>Previous</code> button only if the value of <code>page</code> is greater than <code>1</code>, which means for the first page, we will not see the <code>Previous</code> button.</p>
<p>And If the current value of <code>page</code> is less than the <code>totalPages</code>, then only we show the <code>Next</code> button. This means that for the last page, we will not see the <code>Next</code> button.</p>
<p>If you remember, we have already set the value of <code>totalPages</code> inside the <code>fetchImages</code> function by calling the <code>setTotalPages</code> function, and we're using it above to hide the <code>Next</code> button.</p>
<p>Also, don't forget to add import for <code>Button</code> component from <code>react-bootstrap</code> inside the <code>App</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
</code></pre>
<p>Now, when we click on the <code>Previous</code> button, we need to <code>decrement</code> the value of the <code>page</code> state variable. And when we click on <code>Next</code> button, we need to <code>increment</code> the value of the <code>page</code> state variable.</p>
<p>So, let's add an <code>onClick</code> handler for both of these buttons as shown below:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'buttons'</span>&gt;
  {page &gt; <span class="hljs-number">1</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page - 1)}&gt;Previous<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
  )}
  {page &lt; totalPages &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page + 1)}&gt;Next<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
  )}
&lt;/div&gt;
</code></pre>
<p>Let's console log the value of the <code>page</code> state variable, so we can see the value getting updated.</p>
<p>After <code>handleSelection</code> method, add console.log like this:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'page'</span>, page);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/24_pagination.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying Current Page Value In Console</em></p>
<p>As you can see above, initially for the first page, we don't see a <code>Previous</code> button.</p>
<p>And when we click on the <code>Next</code> button, we see the <code>Previous</code> and <code>Next</code> buttons, and the <code>page</code> value is also incremented by <code>1</code> as you can see in the console.</p>
<p>So, on every <code>Next</code> button click, the <code>page</code> value is incremented by <code>1</code>.  And on every <code>Previous</code> button click, the <code>page</code> value is decremented by <code>1</code>.</p>
<p>And when we come back to the first page, the <code>Previous</code> button is hidden again which is as expected.</p>
<p>As you might have noticed above, the page value changes on click of <code>Previous</code> and <code>Next</code> buttons but a new set of images are not loaded when we click of those buttons.</p>
<p>This is because we're not making the API call again with an updated page value when the page value changes.</p>
<p>So let's do just that.</p>
<p>Add a <code>useEffect</code> hook in the <code>App</code> component like this:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetchImages();
}, [page]);
</code></pre>
<p>Now, every time we click on <code>Previous</code> or <code>Next</code> button, the <code>page</code> value changes, so the above <code>useEffect</code> hook will be executed, where we're calling the <code>fetchImages</code> function to load the next set of images.</p>
<p>Now, If you check the application, you will see images loaded correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/25_loading_next_images.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Loading Next Set Of Images Using Pagination</em></p>
<p>As you can see above, we're correctly loading images when clicked on <code>Previous</code> or <code>Next</code> button.</p>
<p>But there is a small issue.</p>
<p>If we're not on the first or last page, we see the <code>Previous</code> and <code>Next</code> buttons and when we try to search for another term or click on quick search options, we still see the <code>Previous</code> button.</p>
<p>Ideally, when we search for another term or click on another quick search option, we should start from the first page, so only the <code>Next</code> button should be visible. But right now both <code>Previous</code> and <code>Next</code> buttons are visible as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/26_previous_not_resetting.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Issue With Previous Buttons Not Hiding On Search</em></p>
<p>To fix this issue, we need to reset the <code>page</code> state value once we search for another term or click on another quick search option.</p>
<p>So inside the <code>handleSearch</code> and <code>handleSelection</code> methods, call <code>setPage</code> function with a value of <code>1</code> like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  event.preventDefault();
  <span class="hljs-built_in">console</span>.log(searchInput.current.value);
  fetchImages();
  setPage(<span class="hljs-number">1</span>);
};

<span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
  searchInput.current.value = selection;
  fetchImages();
  setPage(<span class="hljs-number">1</span>);
};
</code></pre>
<p>As you can see, we're repeating the <code>fetchImages</code> and <code>setPage</code> function calls in both of these methods.</p>
<p>So, let's create another function with a name <code>resetSearch</code> and move the <code>fetchImages</code> and <code>setPage</code> function calls inside it. Let's call that function from <code>handleSearch</code> and <code>handleSelection</code> methods as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> resetSearch = <span class="hljs-function">() =&gt;</span> {
  setPage(<span class="hljs-number">1</span>);
  fetchImages();
};

<span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  event.preventDefault();
  <span class="hljs-built_in">console</span>.log(searchInput.current.value);
  resetSearch();
};

<span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
  searchInput.current.value = selection;
  resetSearch();
};
</code></pre>
<p>Now, If you check the application, you will see that we always get the correct first page result displayed when clicking on the quick search option or entering any search term which is as expected.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/27_correctly_loading_first_page.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Demo Of Previous Button Hidden On Every Search</em></p>
<p>Your entire <code>App.jsx</code> file will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { useEffect, useRef, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Button, Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">const</span> API_URL = <span class="hljs-string">'https://api.unsplash.com/search/photos'</span>;
<span class="hljs-keyword">const</span> IMAGES_PER_PAGE = <span class="hljs-number">20</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> searchInput = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [images, setImages] = useState([]);
  <span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> [totalPages, setTotalPages] = useState(<span class="hljs-number">0</span>);

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

  <span class="hljs-keyword">const</span> fetchImages = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
      setImages(data.results);
      setTotalPages(data.total_pages);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  };

  <span class="hljs-keyword">const</span> resetSearch = <span class="hljs-function">() =&gt;</span> {
    setPage(<span class="hljs-number">1</span>);
    fetchImages();
  };

  <span class="hljs-keyword">const</span> handleSearch = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(searchInput.current.value);
    resetSearch();
  };

  <span class="hljs-keyword">const</span> handleSelection = <span class="hljs-function">(<span class="hljs-params">selection</span>) =&gt;</span> {
    searchInput.current.value = selection;
    resetSearch();
  };

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'page'</span>, page);

  <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">'title'</span>&gt;</span>Image Search<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">'search-section'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSearch}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">'search'</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Type something to search...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'search-input'</span>
            <span class="hljs-attr">ref</span>=<span class="hljs-string">{searchInput}</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>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'filters'</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> handleSelection('nature')}&gt;Nature<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('birds')}&gt;Birds<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('cats')}&gt;Cats<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">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSelection('shoes')}&gt;Shoes<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">'images'</span>&gt;</span>
        {images.map((image) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{image.id}</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{image.urls.small}</span>
            <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.alt_description}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'image'</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">'buttons'</span>&gt;</span>
        {page &gt; 1 &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page - 1)}&gt;Previous<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        )}
        {page <span class="hljs-tag">&lt; <span class="hljs-attr">totalPages</span> &amp;&amp; (
          &lt;<span class="hljs-attr">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page + 1)}&gt;Next<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">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>
<h2 id="heading-how-to-find-bugs-using-eslint">How to Find Bugs Using ESLint</h2>
<p>When working on a React application, you should always have the ESLint VS Code extension enabled.</p>
<p>This will make sure that your code is correct and it will not produce any unexpected results in the future.</p>
<p>Based on the ESLint configuration defined in the <code>.eslientrc</code> file, you will get helpful suggestions to improve your code.</p>
<p>So, open your VS Code Extensions panel and install the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint">ESLint extension</a> as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/28_eslint_extension.png" alt="Image" width="600" height="400" loading="lazy">
<em>VS Code ESLint Extension</em></p>
<p>After installing the extension, if you check the <code>App.jsx</code> file, you will immediately see a yellow squiggly line for the <code>page</code> dependency of the <code>useEffect</code> hook. If you mouse hover over it, you will see the warning as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/29_missing_dependency.png" alt="Image" width="600" height="400" loading="lazy">
<em>ESLint Warning For useEffect Hook</em></p>
<p>As the warning indicates, we need to add a <code>fetchImages</code> dependency in the dependency array.</p>
<p>We're getting a warning because, in the functional component, on every re-render of the component, all the declared functions are re-created so their reference changes.</p>
<p>So, if we're using any outside variable or function inside the <code>useEffect</code> hook, we need to mention that in the dependencies, so whenever the dependency changes, the <code>useEffect</code> will be executed again.</p>
<p>To fix this, you can click on the quick fix link and select the "update the dependencies" option as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/30_updating_dependency.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Updating useEffect Hook Dependency</em></p>
<p>All the missing dependencies will be automatically added in the dependency array.</p>
<p>You can also choose to manually add the dependency if you want.</p>
<p>However, with this change, you will see a new yellow warning for the <code>fetchImages</code> function as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/31_fetchimages_warning.png" alt="Image" width="600" height="400" loading="lazy">
<em>ESLint Warning For useCallback</em></p>
<p>As I said previously, on every re-render of the component, the <code>fetchImages</code> function will be re-created and when it's changed, we again call the <code>fetchImages</code> function as it's added in the dependency. </p>
<p>To avoid that, we need to wrap the <code>fetchImages</code> function inside the <a target="_blank" href="https://react.dev/reference/react/useCallback">useCallback</a> hook as shown below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
      <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
        searchInput.current.value
      }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
        <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
      }</span>`</span>
    );
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
    setImages(data.results);
    setTotalPages(data.total_pages);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
}, [page]);
</code></pre>
<p>In the above code, we're passing <code>page</code> as a dependency because, <code>page</code> is an external variable whose value might change in the future when we click on <code>Previous</code> or <code>Next</code> buttons or search for any new term.</p>
<p>If changing variables are used inside <code>useEffect</code> or <code>useCallback</code> or <code>useMemo</code> hook, we need to add them in the dependencies list.</p>
<p>Now, you will not see any more warnings in the <code>App</code> component.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/32_no_warnings.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Fixed ESLint Warning of useCallback</em></p>
<p>However, If you check the browser console, you will see an error and nothing is displayed on the UI as the application has crashed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/33_access_before_initialization.png" alt="Image" width="600" height="400" loading="lazy">
<em>Function Expression Related Console Error</em></p>
<p>We're getting errors because we have declared <code>fetchImages</code> function using the function expression syntax, and functions declared using function expression syntax cannot be called before defining them.</p>
<p>Assigning a function to a variable makes it a function expression.</p>
<p>As you can see in the below image, we're calling <code>fetchImages</code> function on line number 16 and we're declaring the function on line number 19 and functions declared using function expression syntax cannot be accessed before the declaration.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/34_function_expression_error.png" alt="Image" width="600" height="400" loading="lazy">
<em>Cause of Console Error</em></p>
<p>To fix this, we need to declare the function before calling it. So, move the <code>fetchImages</code> function before the useEffect hook and it will fix the issue.</p>
<p>Your <code>App</code> component will 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> searchInput = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [images, setImages] = useState([]);
  <span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> [totalPages, setTotalPages] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> fetchImages = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
      setImages(data.results);
      setTotalPages(data.total_pages);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  }, [page]);

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

  <span class="hljs-keyword">const</span> resetSearch = <span class="hljs-function">() =&gt;</span> {
    setPage(<span class="hljs-number">1</span>);
    fetchImages();
  };
  ...
}
</code></pre>
<p>Now, If you check the application, there will not be any error and the application will work as expected.</p>
<h2 id="heading-code-improvements">Code Improvements</h2>
<p>Right now, we have not added any validation in the current application when the user enters a search term.</p>
<p>When the page is loaded, and when we don't enter any text and directly press the enter key in the input search box, we're making an API call which is not good.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/35_extra_api_call.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Demo Of API Calls Made Without Any Value</em></p>
<p>To fix this, before making the API call, we first need to check if the <code>searchInput.current.value</code> is not empty and then only make the API call.</p>
<p>Change the <code>fetchImages</code> function from this code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
      <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
        searchInput.current.value
      }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
        <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
      }</span>`</span>
    );
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
    setImages(data.results);
    setTotalPages(data.total_pages);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
}, [page]);
</code></pre>
<p>to the below code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">if</span> (searchInput.current.value) {
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'data'</span>, data);
      setImages(data.results);
      setTotalPages(data.total_pages);
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
}, [page]);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/36_no_api_calls.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Fixed Issue of API Calls Without Any Value</em></p>
<p>As you can see above, initially on page load and without entering any value, if we press the enter key, no API call is made.</p>
<p>Only when we type something and press enter, the API call is made, which is a good improvement to the application.</p>
<h2 id="heading-how-to-remove-an-extra-dependency-from-useeffect">How to Remove an Extra Dependency From <code>useEffect</code></h2>
<p>As we have added a <code>useCallback</code> hook for the <code>fetchImages</code> function which has a <code>page</code> dependency, we no longer need the extra <code>page</code> dependency for the <code>useEffect</code> hook.</p>
<p>So change the below code:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetchImages();
}, [fetchImages, page]);
</code></pre>
<p>to this code:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetchImages();
}, [fetchImages]);
</code></pre>
<p>and the application will work as before without any issues.</p>
<h2 id="heading-how-to-display-loading-indication">How to Display Loading Indication</h2>
<p>As you might have noticed in the previous image, when we searched for the text <code>hello</code>, the results were not displayed immediately.</p>
<p>As we're making an API call when searching for something, depending on the network speed, it might take some time to get the data from the API.</p>
<p>So while the API call is still going on, we can display a loading message, and once we get the response from the API, we will display the images.</p>
<p>To achieve that, declare a new loading state in the <code>App</code> component with an initial value of <code>false</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>And now change the <code>fetchImages</code> function to the below code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> fetchImages = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">if</span> (searchInput.current.value) {
      setErrorMsg(<span class="hljs-string">''</span>);
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>?query=<span class="hljs-subst">${
          searchInput.current.value
        }</span>&amp;page=<span class="hljs-subst">${page}</span>&amp;per_page=<span class="hljs-subst">${IMAGES_PER_PAGE}</span>&amp;client_id=<span class="hljs-subst">${
          <span class="hljs-keyword">import</span>.meta.env.VITE_API_KEY
        }</span>`</span>
      );
      setImages(data.results);
      setTotalPages(data.total_pages);
      setLoading(<span class="hljs-literal">false</span>);
    }
  } <span class="hljs-keyword">catch</span> (error) {
    setErrorMsg(<span class="hljs-string">'Error fetching images. Try again later.'</span>);
    <span class="hljs-built_in">console</span>.log(error);
    setLoading(<span class="hljs-literal">false</span>);
  }
}, [page]);
</code></pre>
<p>As you can see above, we're calling <code>setLoading(true)</code> before the API call and <code>setLoading(false)</code> after the API call.</p>
<p>Note that, we're also calling <code>`setLoading(false)</code>inside the catch block.</p>
<p>So, even if the API is successful or failed, we're setting <code>loading</code> state to <code>false</code> so we will not see the loading message all the time.</p>
<p>Now, to display the loading message change the below code:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">'images'</span>&gt;
  {images.map(<span class="hljs-function">(<span class="hljs-params">image</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">key</span>=<span class="hljs-string">{image.id}</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">{image.urls.small}</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.alt_description}</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">'image'</span>
    /&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">'buttons'</span>&gt;</span>
  {page &gt; 1 &amp;&amp; (
    <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page - 1)}&gt;Previous<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
  )}
  {page <span class="hljs-tag">&lt; <span class="hljs-attr">totalPages</span> &amp;&amp; (
    &lt;<span class="hljs-attr">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page + 1)}&gt;Next<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
  )}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>to this code:</p>
<pre><code class="lang-jsx">{loading ? (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'loading'</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
) : (
  <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'images'</span>&gt;</span>
      {images.map((image) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
          <span class="hljs-attr">key</span>=<span class="hljs-string">{image.id}</span>
          <span class="hljs-attr">src</span>=<span class="hljs-string">{image.urls.small}</span>
          <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.alt_description}</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">'image'</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">'buttons'</span>&gt;</span>
      {page &gt; 1 &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page - 1)}&gt;Previous<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      )}
      {page <span class="hljs-tag">&lt; <span class="hljs-attr">totalPages</span> &amp;&amp; (
        &lt;<span class="hljs-attr">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setPage(page + 1)}&gt;Next<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/&gt;</span></span>
)}
</code></pre>
<p>In the above code, if loading is true, then we're displaying a loading message. Otherwise, we're displaying the images coming from the API.</p>
<p>If you check the application, you will see that the loading indication is displaying correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/37_loading_indication.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Loading Indication Demo</em></p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for Reading</strong></h2>
<p>That's it for this tutorial. I hope you learned a lot from it.</p>
<p>You can find the complete source code for this application in <a target="_blank" href="https://github.com/myogeshchavan97/unsplash_image_search">this repository</a>.</p>
<p>Want to watch the video version of this tutorial? You can check out <a target="_blank" href="https://www.youtube.com/watch?v=0YoT44j3Jg4&amp;list=PLSJnlFr3D-mFm7-cdhnHdBvUdxUp-a9HL&amp;index=17">this video.</a></p>
<p>If you want to master JavaScript, ES6+, React, and Node.js with easy-to-understand content, check out my <a target="_blank" href="https://www.youtube.com/@codingmastery_dev/">YouTube channel</a>. Don't forget to subscribe.</p>
<p>Want to stay up to date with regular content on JavaScript, React, and Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use JavaScript Promises – Callbacks, Async/Await, and Promise Methods Explained ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will learn everything you need to know about using promises and async/await in JavaScript. So let's get started. If you'd like to learn along with a video version of this tutorial, you can also check out my YouTube playlist. Why... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascript-promises-async-await-and-promise-methods/</link>
                <guid isPermaLink="false">66bc5521e35f27b353950745</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Tue, 15 Aug 2023 16:03:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/promises_async_methods.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will learn everything you need to know about using promises and async/await in JavaScript.</p>
<p>So let's get started.</p>
<p>If you'd like to learn along with a video version of this tutorial, you can also check out my <a target="_blank" href="https://www.youtube.com/watch?v=4jaiXP6vU2w&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=14">YouTube playlist</a>.</p>
<h2 id="heading-why-use-promises-in-javascript">Why Use Promises in JavaScript?</h2>
<p>ES6 introduced promises as a native implementation. Before ES6 we were using callbacks to handle asynchronous operations.</p>
<p>Let’s understand what callbacks are and what problem related to callbacks is solved by promises.</p>
<p>Let's say we have a list of posts and their respective comments, like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> posts = [
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">post_title</span>: <span class="hljs-string">'First Post'</span> },
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">post_title</span>: <span class="hljs-string">'Second Post'</span> },
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">post_title</span>: <span class="hljs-string">'Third Post'</span> },
];

<span class="hljs-keyword">const</span> comments = [
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">comment</span>: <span class="hljs-string">'Great!'</span>},
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">comment</span>: <span class="hljs-string">'Nice Post!'</span>},
  { <span class="hljs-attr">post_id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">comment</span>: <span class="hljs-string">'Awesome Post!'</span>},
];
</code></pre>
<p>Now, we will write a function to get a post by passing the post id. If the post is found, we will retrieve the comments related to that post.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getPost = <span class="hljs-function">(<span class="hljs-params">id, callback</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> post = posts.find( <span class="hljs-function"><span class="hljs-params">post</span> =&gt;</span> post.post_id === id);
 <span class="hljs-keyword">if</span>(post) {
   callback(<span class="hljs-literal">null</span>, post);
 } <span class="hljs-keyword">else</span> {
   callback(<span class="hljs-string">"No such post found"</span>, <span class="hljs-literal">undefined</span>);
 }
};

<span class="hljs-keyword">const</span> getComments = <span class="hljs-function">(<span class="hljs-params">post_id, callback</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> result = comments.filter( <span class="hljs-function"><span class="hljs-params">comment</span> =&gt;</span> comment.post_id === post_id);
 <span class="hljs-keyword">if</span>(result) {
   callback(<span class="hljs-literal">null</span>, result);
 } <span class="hljs-keyword">else</span> {
   callback(<span class="hljs-string">"No comments found"</span>, <span class="hljs-literal">undefined</span>);
 }
}
</code></pre>
<p>In the above <code>getPost</code> and <code>getComments</code> functions, if there is an error we will pass it as the first argument. But if we get the result, we will call the callback function and pass the result as the second argument to it.</p>
<p>If you are familiar with Node.js, then you will know that this is a very common pattern used in every Node.js callback function.</p>
<p>Now let’s use those functions:</p>
<pre><code class="lang-js">getPost(<span class="hljs-number">2</span>, <span class="hljs-function">(<span class="hljs-params">error, post</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span>(error) {
     <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(error);
    }
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Post:'</span>, post);
    getComments(post.post_id, <span class="hljs-function">(<span class="hljs-params">error, comments</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span>(error) {
          <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(error);
        }
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Comments:'</span>, comments);
    });
});
</code></pre>
<p>After executing the above code, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/posts.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Result of calling getPost and getComments function</em></p>
<p>Here's a <a target="_blank" href="https://codepen.io/myogeshchavan97/pen/PoweVgR?editors=0011#0">CodePen Demo</a>.</p>
<p>As you can see, we have the <code>getComments</code> function nested inside the <code>getPost</code> callback. </p>
<p>Now imagine if we also wanted to find the likes of those comments. That would also get nested inside <code>getComments</code> callback, creating more nesting. This will eventually make the code difficult to understand.</p>
<p>This nesting of the callbacks is known as <strong>callback hell.</strong></p>
<p>You can see that the error handling condition also gets repeated in the code, which creates duplicate code – this is not good.</p>
<p>So to fix this problem and allow asynchronous operations, promises were introduced.</p>
<h2 id="heading-what-are-promises-in-javascript">What are Promises in JavaScript?</h2>
<p>Promises are one of the most important parts of JavaScript – but they can be confusing and difficult to understand. Many new devs, as well as experienced ones, struggle to fully grasp them.</p>
<p>So what is a promise? A promise represents an asynchronous operation whose result will come in the future.</p>
<p>Before ES6, there was no way to wait for something to perform some operation. For example, when we wanted to make an API call, there was no way to wait until the results came back.</p>
<p>For that, we used to use external libraries like JQuery or Ajax which had their own implementation of promises. But there was no JavaScript implementation of promises.</p>
<p>But then promises were added in ES6 as a native implementation. And now, using promises in ES6, we can make an API call ourselves and wait until it's done to perform some operation.</p>
<h2 id="heading-how-to-create-a-promise">How to Create a Promise</h2>
<p>To create a promise we need to use the <code>Promise</code> constructor function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{

});
</code></pre>
<p>The <code>Promise</code> constructor takes a function as an argument and that function internally receives <code>resolve</code> and <code>reject</code> as parameters.</p>
<p>The <code>resolve</code> and <code>reject</code> parameters are actually functions that we can call depending on the outcome of the asynchronous operation.</p>
<p>A <code>Promise</code> can go through three states:</p>
<ul>
<li>Pending</li>
<li>Fulfilled</li>
<li>Rejected</li>
</ul>
<p>When we create a promise, it’s in a pending state. When we call the <code>resolve</code> function, it goes in a fulfilled state, and if we call <code>reject</code> it will go into the rejected state.</p>
<p>To simulate the long-running or asynchronous operation, we will use the <code>setTimeout</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
 <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span>;
  resolve(sum);
 }, <span class="hljs-number">2000</span>);
});
</code></pre>
<p>Here, we've created a promise which will resolve to the sum of <code>4</code> and <code>5</code> after a 2000ms (2 second) timeout is over.</p>
<p>To get the result of the successful promise execution, we need to register a callback handler using <code>.then</code> like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
 <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span>;
  resolve(sum);
 }, <span class="hljs-number">2000</span>);
});

promise.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// 9</span>
});
</code></pre>
<p>So whenever we call <code>resolve</code>, the promise will return back the value passed to the <code>resolve</code> function which we can collect using the <code>.then</code> handler.</p>
<p>If the operation is not successful, then we call the <code>reject</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
 <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span> + <span class="hljs-string">'a'</span>;
  <span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(sum)) {
    reject(<span class="hljs-string">'Error while calculating sum.'</span>);
  } <span class="hljs-keyword">else</span> {
    resolve(sum);
  }
 }, <span class="hljs-number">2000</span>);
});

promise.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(result);
});
</code></pre>
<p>Here, if the <code>sum</code> is not a number, then we call the <code>reject</code> function with the error message. Otherwise, we call the <code>resolve</code> function.</p>
<p>If you execute the above code, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promises_fcc.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of rejecting promise without catch handler</em></p>
<p>As you can see, we're getting an uncaught error message along with the message we've specified because calling the <code>reject</code> function throws an error. But we have not added an error handler for catching that error.</p>
<p>To catch the error, we need to register another callback using <code>.catch</code> like this:</p>
<pre><code class="lang-js">promise.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(result);
}).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
 <span class="hljs-built_in">console</span>.log(error);
});
</code></pre>
<p>You will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/error_catch.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of rejecting promise with catch handler</em></p>
<p>As you can see, we have added the <code>.catch</code> handler, so we're not getting any uncaught error – we're just logging the error to the console.</p>
<p>This also avoids stopping your application abruptly.</p>
<p>So it's always recommended to add the <code>.catch</code> handler to every promise so your application will not stop running because of the error.</p>
<h3 id="heading-when-to-use-resolve-and-reject">When to Use <code>resolve</code> and <code>reject</code></h3>
<p>Let's take an example of an API call.</p>
<p>If you're making an API call and the API call is successful, then you call the <code>resolve</code> function by passing the result of the API as an argument to it.</p>
<p>And if the API is unsuccessful, then you call the <code>reject</code> function by passing any message as an argument to it.</p>
<p>So to indicate that the operation is successful, we call the <code>resolve</code> function and for indicating an unsuccessful operation, we call the <code>reject</code> function.</p>
<h2 id="heading-what-is-promise-chaining-and-why-is-it-useful">What is Promise Chaining and Why is it Useful?</h2>
<p>Promise chaining is a technique used to manage asynchronous operations in a more organized and readable way.</p>
<p>In promise chaining, we can attach multiple <code>.then</code> handlers in which result of previous <code>.then</code> handler is automatically passed to the next <code>.then</code> handler.</p>
<p>Using promise chaining helps to avoid the problem of callback hell which we have seen previously.</p>
<p>Promise chaining also allows us to write asynchronous code in a more linear and sequential manner, which is easier to read and understand.</p>
<p>Also, when using promise chaining, we can attach only one<code>.catch</code> handler at the end of all the <code>.then</code> handlers. If any of the in-between promises fail, the last <code>.catch</code> handler will be automatically executed.</p>
<p>So we don't need to add multiple <code>.catch</code> handlers. This eliminates multiple error check as we did in the callback hell example previously.</p>
<h2 id="heading-how-promise-chaining-works">How Promise Chaining Works</h2>
<p>We can add multiple <code>.then</code> handlers to a single promise like this:</p>
<pre><code class="lang-js">promise.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'first .then handler'</span>);
 <span class="hljs-keyword">return</span> result;
}).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'second .then handler'</span>);
 <span class="hljs-built_in">console</span>.log(result);
}).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
 <span class="hljs-built_in">console</span>.log(error);
});
</code></pre>
<p>When we have multiple <code>.then</code> handlers added, the return value of the previous <code>.then</code> handler is automatically passed to the next <code>.then</code> handler.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_chaining.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of promise chaining</em></p>
<p>As you can see, adding <code>4 + 5</code> resolves a promise and we get that sum in the first <code>.then</code> handler. There we're printing a log statement and return that sum to the next <code>.then</code> handler.</p>
<p>And inside the next <code>.then</code> handler, we're adding a log statement and then we're printing the result we got from the previous <code>.then</code> handler.</p>
<p>This way of adding multiple <code>.then</code> handlers is known as promise chaining.</p>
<h2 id="heading-how-to-delay-a-promises-execution-in-javascript">How to Delay a Promise's Execution in JavaScript</h2>
<p>Many times we don't want the promise to execute immediately. Rather, we want it to delay until after some operation is completed.</p>
<p>To achieve this, we can wrap the promise in a function and return that promise from that function like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createPromise</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span>;
   <span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(sum)) {
     reject(<span class="hljs-string">'Error while calculating sum.'</span>);
   } <span class="hljs-keyword">else</span> {
    resolve(sum);
   }
  }, <span class="hljs-number">2000</span>);
 });
}
</code></pre>
<p>This way, we can use the function parameters inside the promise, making the function truly dynamic.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createPromise</span>(<span class="hljs-params">a, b</span>) </span>{
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> sum = a + b;
   <span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(sum)) {
     reject(<span class="hljs-string">'Error while calculating sum.'</span>);
   } <span class="hljs-keyword">else</span> {
    resolve(sum);
   }
  }, <span class="hljs-number">2000</span>);
 });
}

createPromise(<span class="hljs-number">1</span>,<span class="hljs-number">8</span>)
 .then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">output</span>) </span>{
  <span class="hljs-built_in">console</span>.log(output); <span class="hljs-comment">// 9</span>
});

<span class="hljs-comment">// OR</span>

createPromise(<span class="hljs-number">10</span>,<span class="hljs-number">24</span>)
 .then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">output</span>) </span>{
  <span class="hljs-built_in">console</span>.log(output); <span class="hljs-comment">// 34</span>
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/general_function.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of delaying promise execution</em></p>
<p><strong>Note:</strong> When we create a promise, it will be either resolved or rejected but not both at the same time. So we cannot add two <code>resolve</code> or <code>reject</code> function calls in the same promise.</p>
<p>Also, we can pass only a single value to the <code>resolve</code> or <code>reject</code> function.</p>
<p>If you want to pass multiple values to a <code>resolve</code> function, pass it as an object like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>{
 <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span>;
  resolve({
   <span class="hljs-attr">a</span>: <span class="hljs-number">4</span>,
   <span class="hljs-attr">b</span>: <span class="hljs-number">5</span>,
   sum
  });
 }, <span class="hljs-number">2000</span>);
});

promise.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
 <span class="hljs-built_in">console</span>.log(result);
}).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
 <span class="hljs-built_in">console</span>.log(error);
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/object_resolve.png" alt="Image" width="600" height="400" loading="lazy">
<em>Passing object to resolve function to return multiple values</em></p>
<h2 id="heading-how-to-use-arrow-functions-in-javascript">How to Use Arrow Functions in JavaScript</h2>
<p>In all the above code examples, we've used regular ES5 function syntax while creating promises. </p>
<p>But it's a common practice to use arrow function syntax instead of ES5 function syntax.</p>
<p>So let's first understand what is an arrow function and how to use it.</p>
<h3 id="heading-what-are-arrow-functions">What are arrow functions?</h3>
<p>Before ES6, there were two main ways of declaring functions.</p>
<ol>
<li>Function Declaration Syntax:</li>
</ol>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
 <span class="hljs-keyword">return</span> a + b;
}
</code></pre>
<ol start="2">
<li>Function Expression Syntax:</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> add = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{
 <span class="hljs-keyword">return</span> a + b;
};
</code></pre>
<p><strong>The</strong> main visible <strong>difference between the</strong> regular <strong>function and arrow function is the syntax of writing the function.</strong></p>
<p>Using arrow function syntax, we can write the above adding function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
 <span class="hljs-keyword">return</span> a + b;
};
</code></pre>
<p>You might not see much difference here, apart from the arrow. But if we have a single line of code in the function body we can simplify the above arrow function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;
</code></pre>
<p>Here we are implicitly returning the result of <code>a + b</code>, so there is no need for a <code>return</code> keyword if there is a single statement.</p>
<p>So using the arrow functions will make your code much shorter.</p>
<p>If you want to learn other features of arrow functions, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=tI87o_kDKN4&amp;list=PLSJnlFr3D-mGIHFpo80ylsaBErtueSpYS&amp;index=4">this video</a>.</p>
<p>Using an arrow function, we can write the previous code as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
 <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sum = <span class="hljs-number">4</span> + <span class="hljs-number">5</span> + <span class="hljs-string">'a'</span>;
  <span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(sum)) {
    reject(<span class="hljs-string">'Error while calculating sum.'</span>);
  } <span class="hljs-keyword">else</span> {
    resolve(sum);
  }
 }, <span class="hljs-number">2000</span>);
});

promise.then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(result);
});
</code></pre>
<p>You can either use ES5 or ES6 function syntax depending on your preferences and needs.</p>
<h2 id="heading-how-to-use-asyncawait-in-javascript">How to Use Async/Await in JavaScript</h2>
<p>In this section, we'll explore everything you need to know about async/await.</p>
<p>Async/await gives developers a better way to use promises.</p>
<p>To use async/await, you need to create a function and add the <code>async</code> keyword before the function name using ES5 function declaration syntax like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">someFunction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// function body</span>
}
</code></pre>
<p>or using function expression syntax like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> someFunction = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// function body</span>
};
</code></pre>
<p>or using an arrow function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> someFunction = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-comment">// function body</span>
};
</code></pre>
<p>Always remember that, when you add the async keyword to the function, it always returns a promise.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sayHello = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">'Hello'</span>;
};

sayHello();
</code></pre>
<p>What do you think the output of the above code will be?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/async_1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of calling function marked as async</em></p>
<p>The output is a promise fulfilled with the string <code>Hello</code>.</p>
<p>So the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sayHello = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">'Hello'</span>;
};
</code></pre>
<p>is the same as this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sayHello = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  resolve(<span class="hljs-string">'Hello'</span>);
 });
}
</code></pre>
<p>which is the same as this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sayHello = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.resolve(<span class="hljs-string">'Hello'</span>);
};
</code></pre>
<p><code>Promise.resolve('Hello')</code> is just a shorter way of creating a promise which resolves to the string <code>Hello</code>.</p>
<p>So to get the actual string <code>Hello</code>, we need to add the <code>.then</code> handler like this:</p>
<pre><code class="lang-js">sayHello().then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">result</span>) </span>{
  <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// Hello</span>
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/async_hello.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting result of async function using .then handler</em></p>
<p>Now, where do we use the <code>await</code> keyword?</p>
<p>It's used inside the function which is declared as <code>async</code>. So the <code>await</code> keyword should only be used inside the <code>async</code> function.</p>
<p>You will get an error if you try to use it in non-async functions.</p>
<p>Suppose, we have a promise which returns the product of two numbers like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getProduct</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">resolve, reject</span>) </span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      resolve(a * b);
    }, <span class="hljs-number">1000</span>);
  });
}
</code></pre>
<p>and we're using it like this:</p>
<pre><code class="lang-js">getProduct(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>)
  .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">result</span>) </span>{
    getProduct(result, <span class="hljs-number">2</span>)
      .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">finalResult</span>) </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'final_result'</span>, finalResult);
      })
      .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
        <span class="hljs-built_in">console</span>.log(error);
      });
  })
  .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
    <span class="hljs-built_in">console</span>.log(error);
  });
</code></pre>
<p>In the above code, we're first getting the product of <code>2</code> and <code>4</code>. Then we're using that result to multiply it by <code>2</code> again, and then finally printing the product.</p>
<p>If you execute the above code, you will see the final result as 16 which is 2 <em> 4 = 8 and 8 </em> 2 = 16.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/async_product.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of nesting .then callback handlers</em></p>
<p>The above code of  <code>.then</code> and <code>.catch</code> looks pretty complicated and difficult to understand at one glance.</p>
<p>So using async/await we can simplify the above code to this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> printResult = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> getProduct(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>); <span class="hljs-comment">// line 1</span>
    <span class="hljs-keyword">const</span> finalResult = <span class="hljs-keyword">await</span> getProduct(result, <span class="hljs-number">2</span>); <span class="hljs-comment">// line 2</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'final_result'</span>, finalResult); <span class="hljs-comment">// line 3</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};

printResult();
</code></pre>
<p>This looks much cleaner and easy to understand.</p>
<p>Here, to use the <code>await</code> keyword, we're declaring a function with the <code>async</code> keyword. Then to get the result of each promise, we're adding the <code>await</code> keyword in front of it.</p>
<p>Also, note that we've added try/catch inside the function. You always need to add a try block around the code which uses <code>await</code> so the catch block will be executed if the promise gets rejected.</p>
<p>There is a very important thing you need to remember: The above async/await code will work exactly the same as when we use <code>.then</code> – so the next <code>await</code> line (line 2) will not be executed until the previous <code>await</code> call (line 1) is successful.</p>
<p>Therefore, as the <code>getProduct</code> function is taking 1 second to execute because of the setTimeout call, line 2 will have to wait for 1 second before executing the <code>getProduct</code> function again.</p>
<p>But there is one exception to this behavior, which you can check out in <a target="_blank" href="https://levelup.gitconnected.com/common-gotcha-with-promises-693a993568c2?source=friends_link&amp;sk=32d92e34511f72cbcc399cded49348c8">this article</a>.</p>
<p>Also, if there is an error while executing line 1 (because of some error that occurred in the <code>getProduct</code> function), the next code after line 1 will not be executed. Instead, the catch block will be executed.</p>
<p>Now, if you compare the code of promise chaining and async/await, you will see the difference.</p>
<pre><code class="lang-js"><span class="hljs-comment">// code using async/await</span>

<span class="hljs-keyword">const</span> printResult = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> product = <span class="hljs-keyword">await</span> getProduct(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>); <span class="hljs-comment">// line 1</span>
    <span class="hljs-keyword">const</span> finalResult = <span class="hljs-keyword">await</span> getProduct(product, <span class="hljs-number">2</span>); <span class="hljs-comment">// line 2</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'final_result'</span>, finalResult); <span class="hljs-comment">// line 3</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};

printResult();
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// code using .then and .catch</span>

getProduct(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>)
  .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">result</span>) </span>{
    getProduct(result, <span class="hljs-number">2</span>)
      .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">finalResult</span>) </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'final_result'</span>, finalResult);
      })
      .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
        <span class="hljs-built_in">console</span>.log(error);
      });
  })
  .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
    <span class="hljs-built_in">console</span>.log(error);
  });
</code></pre>
<p>As you can see, the code using async/await is much cleaner and easy to understand as compared to the promise chaining.</p>
<p>As the nesting gets deeper, the code using promise chaining gets more complicated. So async/await just provides a way to write the same code but with better clarity.</p>
<p>Using async/await also reduces the need of adding multiple <code>.catch</code> handlers to handle the errors.</p>
<p>We can avoid the nesting in the above promise chaining by writing the previous code like this:</p>
<pre><code class="lang-js">getProduct(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>)
  .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">result</span>) </span>{
    <span class="hljs-keyword">return</span> getProduct(result, <span class="hljs-number">2</span>);
  })
  .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">finalResult</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'final_result'</span>, finalResult);
  })
  .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
    <span class="hljs-built_in">console</span>.log(error);
  });
</code></pre>
<p>Here, from the first <code>.then</code> handler, we're returning the result of <code>getProduct(result, 2)</code>.</p>
<p>Whatever returned from the previous <code>.then</code> handler will be passed to the next <code>.then</code> handler.</p>
<p>As the <code>getProduct</code> function returns a promise so we can attach <code>.then</code> again to it and avoid the need for a nested <code>.catch</code> handler.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/avoid_nested_handlers.png" alt="Image" width="600" height="400" loading="lazy">
<em>using promise chaining</em></p>
<p>But still async/await syntax looks cleaner and easier to understand than the promise chaining syntax.</p>
<h2 id="heading-promise-methods">Promise Methods</h2>
<p>In this section, we'll explore the various methods provided by the Promise API.</p>
<p>All these methods are useful when you want to execute multiple asynchronous tasks at the same time when those tasks are not dependent on each other (which saves a lot of time).</p>
<p>Because if you execute each task one after the other, then you have to wait for the previous task to finish before you can start with the next task.</p>
<p>And if the tasks are not related to each other, there is no point in waiting for the previous task to finish before executing the next task.</p>
<h3 id="heading-the-promiseall-method">The <code>Promise.all</code> method</h3>
<p>This method is used to execute multiple asynchronous tasks simultaneously without having to wait for another task to finish.</p>
<p>Suppose we have three promises and all are resolved successfully:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise1 success'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise2 success'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));
</code></pre>
<p>Now, let's use the <code>Promise.all</code> method.</p>
<p><code>Promise.all</code> needs an array of promises as its argument.</p>
<pre><code class="lang-js"><span class="hljs-built_in">Promise</span>.all([promise1, promise2, promise3])
  .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result); <span class="hljs-comment">// resolved ["promise1 success", "promise2 success", "promise3 success"]</span>
  })
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'rejected'</span>, error);
  });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_all.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As all the promises are resolved, <code>result</code> will be an array containing the results of the resolved promises.</p>
<p>Now, what if any of the promises get rejected?</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise1 success'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise2 failure'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));

<span class="hljs-built_in">Promise</span>.all([promise1, promise2, promise3])
  .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result);
  })
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'rejected'</span>, error); <span class="hljs-comment">// rejected promise2 failure</span>
  });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_all_rejected.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the above code, promise2 is rejected so the catch handler will be executed, and in the case of <code>Promise.all</code>:</p>
<ul>
<li>If one of the promises is rejected, the <code>error</code> will contain the error message of the failed promise (as in our case above)</li>
<li>If multiple promises are rejected, the <code>error</code> will be the error message of the first failed promise.</li>
</ul>
<p>Note: Even though the intermediate promise gets rejected, all next promises will not be stopped from executing. They will all be executed – but only the first rejected promise value will be available in the error parameter of the catch block.</p>
<h3 id="heading-the-promiserace-method">The <code>Promise.race</code> method</h3>
<p>Consider again the three resolved promises:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise1 success'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise2 success'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));

<span class="hljs-built_in">Promise</span>.race([promise1, promise2, promise3])
  .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result); <span class="hljs-comment">// resolved promise1 success</span>
  })
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'rejected'</span>, error);
  });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_race_success.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see here, as soon as the first promise gets resolved, the <code>Promise.race</code> method will return the result of that resolved promise. </p>
<p>Now, take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise1 failure'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise2 success'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));

<span class="hljs-built_in">Promise</span>.race([promise1, promise2, promise3])
  .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result);
  })
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'rejected'</span>, error); <span class="hljs-comment">// rejected promise1 failure</span>
  });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_race_failed.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see here, the first promise itself is rejected so the <code>.catch</code> handler will be executed.</p>
<p>So when we use the <code>Promise.race</code> method, it will wait until the first promise gets resolved or rejected and then:</p>
<ul>
<li>If the first promise in the promise chain gets resolved, the <code>.then</code> handler will be executed and the result will be the result of the first resolved promise.</li>
<li>If the first promise in the promise chain gets rejected, the <code>.catch</code> handler will be executed and the result will be the result of the first failed promise.</li>
<li>If multiple promises are rejected, the <code>.catch</code> handler will be executed and the result will be the result of the first failed promise.</li>
</ul>
<h3 id="heading-the-promiseallsettled-method">The <code>Promise.allSettled</code> method</h3>
<p>This method is useful when you want to know the result of each task even though they are rejected.</p>
<p>Because in <code>Promise.all</code> and <code>Promise.race</code>, we get only the result of the first rejected promise and there is no way to get the result of other successful or failed promises.</p>
<p>So using <code>Promise.allSettled</code> we can get the result of all the promises, even if they failed.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise1 success'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise2 success'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));

<span class="hljs-built_in">Promise</span>.allSettled([promise1, promise2, promise3]).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result);
});

<span class="hljs-comment">/* output from `.then`:
resolved [
  {
    "status": "fulfilled",
    "value": "promise1 success"
  },
  {
    "status": "fulfilled",
    "value": "promise2 success"
  },
  {
    "status": "fulfilled",
    "value": "promise3 success"
  }
]
*/</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_allsettled_success.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, the <code>Promise.allSettled</code> method waits until all the promises are resolved or rejected and the <code>result</code> will contain the result of each promise.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise1 failure'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise2 success'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> resolve(<span class="hljs-string">'promise3 success'</span>));

<span class="hljs-built_in">Promise</span>.allSettled([promise1, promise2, promise3]).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result);
});

<span class="hljs-comment">/* output from `.then`:
resolved [
  {
    "status": "rejected",
    "reason": "promise1 failure"
  },
  {
    "status": "fulfilled",
    "value": "promise2 success"
  },
  {
    "status": "fulfilled",
    "value": "promise3 success"
  }
]
*/</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_allsettled_failure.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the above case, even though the first promise is rejected, we get the result of all the promises inside the <code>.then</code> handler.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise1 failure'</span>));
<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise2 failure'</span>));
<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> reject(<span class="hljs-string">'promise3 failure'</span>));

<span class="hljs-built_in">Promise</span>.allSettled([promise1, promise2, promise3]).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'resolved'</span>, result);
});

<span class="hljs-comment">/* output from `.then`:
 resolved [
  {
    "status": "rejected",
    "reason": "promise1 failure"
  },
  {
    "status": "rejected",
    "reason": "promise2 failure"
  },
  {
    "status": "rejected",
    "reason": "promise3 failure"
  }
] 
*/</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/promise_allsettled_multiple_failure.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, even though all the promises are rejected, still the <code>.then</code> handler will be executed and we get the result of each promise.</p>
<p>Want to learn how to use these promise methods in an actual React application? Check out my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-a-hacker-news-clone-using-react/">previous article</a>.</p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for Reading!</strong></h2>
<p>That's it for this tutorial. I hope you learned a lot from it.</p>
<p>Want a video version of this tutorial, check out my Y<a target="_blank" href="https://bit.ly/3E00PlH">ouTube playlist</a>.</p>
<p>If you want to master JavaScript, ES6+, React and Node.js with easy-to-understand content, do check out my <a target="_blank" href="https://www.youtube.com/@codingmastery_dev/">YouTube channel</a> and don't forget to subscribe.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Testing Library Tutorial – How to Write Unit Tests for React Apps ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will learn how to confidently write unit tests using the Testing Library. It is a very popular React testing library for writing unit tests. So let's get started. What We'll Cover: Why Do You Need to Write Unit Tests? What is t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/write-unit-tests-using-react-testing-library/</link>
                <guid isPermaLink="false">66bc553b95b2a9e41d4e968c</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Wed, 30 Nov 2022 16:53:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/cover_testing.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will learn how to confidently write unit tests using the <a target="_blank" href="https://testing-library.com/">Testing Library</a>. It is a very popular React testing library for writing unit tests.</p>
<p>So let's get started.</p>
<h2 id="heading-what-well-cover">What We'll Cover:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-why-do-you-need-to-write-unit-tests">Why Do You Need to Write Unit Tests?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-the-react-testing-library">What is the React Testing Library?</a></li>
<li><a class="post-section-overview" href="#heading-what-not-to-test-with-the-testing-library">What Not to Test with the Testing Library</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-a-react-project-with-vite">How to Setup a React Project with Vite</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-the-testing-library-and-jest-in-a-react-project">How to Set Up the Testing Library and Jest in a React Project</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-ui-for-testing">How to Create the UI for Testing</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-unit-test-cases">How to Write Unit Test Cases</a></li>
<li><a class="post-section-overview" href="#heading-lets-write-some-more-tests">Let's Write Some More Tests</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<p>If you want to learn the React Testing Library in depth from scratch, you can check out my <a target="_blank" href="https://online-elearning-platform.netlify.app/">MERN stack course</a>. </p>
<h2 id="heading-why-do-you-need-to-write-unit-tests">Why Do You Need to Write Unit Tests?</h2>
<p>You might think that you don't need to write so many unit test cases and that it's a waste of time. Perhaps you can manually test the application instead.</p>
<p>Well, you're right – you can certainly do that. But as the application grows, it might be difficult to test all the scenarios in the application and you might miss something. Even a small change might break the application if all the major functionality is not tested properly.</p>
<p>That's why I recommend writing unit test cases covering all those scenarios which you're manually going through as a user.</p>
<p>So by executing just a single command you will be able to know if something is broken in your application or if some test is failing.</p>
<h2 id="heading-what-is-the-react-testing-library">What is the React Testing Library?</h2>
<p>The React <a target="_blank" href="https://testing-library.com/">Testing Library</a> has a set of packages that help you test UI components in a user-centric way. This means it tests based on how the user interacts with the various elements displayed on the page.</p>
<p>So what happens is when the user clicks any button or types in any of the input textboxes, that interaction is tested using this testing library.</p>
<p>So instead of the user doing this testing manually (which takes a lot of time, and the user might miss testing certain scenarios when the application grows), the testing is done by writing unit test cases and executing them by just a single command.</p>
<h2 id="heading-what-not-to-test-with-the-testing-library">What Not to Test with the Testing Library</h2>
<p>Testing Library encourages you to avoid testing implementation details like the internals of a component you're testing.</p>
<p>The guiding principles of this library emphasize a focus on tests that closely resemble how users interact with your web pages.</p>
<p>You may want to avoid testing the following implementation details:</p>
<ul>
<li>Internal state of a component</li>
<li>Internal methods of a component</li>
<li>Lifecycle methods of a component</li>
<li>Child components</li>
</ul>
<p>So if you have experience with <a target="_blank" href="https://enzymejs.github.io/enzyme/">enzyme testing</a>, you might be checking the value of state once you click any button or you might be checking the prop value If something changes.</p>
<p>But these types of checks are not necessary for testing with the React testing library. Instead, in the React testing library, you check the behavior of the DOM when the user clicks on a button or submits a form and so on.</p>
<h2 id="heading-how-to-setup-a-react-project-with-vite">How to Setup a React Project with Vite</h2>
<p>To set up our app that we'll test, we'll be using <a target="_blank" href="https://vitejs.dev/">Vite</a>. It's a popular and faster alternative to <a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">create-react-app</a>.</p>
<p>We'll use Vite because <code>create-react-app</code> becomes slow when the application grows and takes a lot of time to refresh the page when we make any changes in the application code. Also, by default, it also adds a lot of extra packages which we rarely need.</p>
<p>Vite just rebuilds the things we changed, instead of rebuilding the entire application which saves a lot of time during development.</p>
<p>Keep in mind that Vite requires Node.js version 14.18+, so make sure to install a Node version greater than or equal to 14.18.</p>
<p>The easiest and simplest way to install and switch Node.js versions is to use <a target="_blank" href="https://github.com/nvm-sh/nvm#installing-and-updating">nvm</a>.</p>
<p>Even if you're using <code>create-react-app</code>, all the tests you will learn in this tutorial should run exactly the same without any errors.</p>
<p>To create a new Vite project with React, execute the <code>npm init vite</code> command from the terminal.</p>
<p>It will ask you the <code>project name</code>, <code>framework</code>, and <code>variant</code>.</p>
<ul>
<li>For <code>project name</code>, you can enter <code>testing-library-demo</code> or any name of your choice.</li>
<li>For <code>framework</code>, select <code>React</code> from the list of options</li>
<li>For <code>variant</code>, select <code>JavaScript</code> from the list of options</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/1_setup.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new React project using Vite</em></p>
<p>Once the project is created, you can open that project in your favorite IDE.</p>
<p>The project folder structure will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/2_folder_structure.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder structure of React Vite project</em></p>
<p>Now, execute the <code>yarn</code> or <code>npm install</code> command to install all the packages from the <code>package.json</code> file.</p>
<p>Once all the packages are installed, you can execute the <code>yarn run dev</code> or <code>npm run dev</code> command to start the created React application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/3_app_started.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running a React app</em></p>
<p>Now, if you access the displayed URL <code>http://127.0.0.1:5173/</code> you will be able to see the default React application created using Vite.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/4_app_loaded.png" alt="Image" width="600" height="400" loading="lazy">
<em>Default React page rendered using Vite</em></p>
<p>So let's see how we can set up the <a target="_blank" href="https://testing-library.com/docs/">Testing Library</a> in our Vite project.</p>
<h2 id="heading-how-to-set-up-the-testing-library-and-jest-in-a-react-project">How to Set Up the Testing Library and Jest in a React Project</h2>
<p>You can't just use the testing library alone – you also need to install <a target="_blank" href="https://jestjs.io/">Jest</a>. It exposes an extensively used global expect function and other things which help you make assertions in your test cases.</p>
<p>To set up <a target="_blank" href="https://testing-library.com/">Testing library</a> and <a target="_blank" href="https://jestjs.io/">Jest</a>, you need to install the Jest and Testing Library packages as dev dependencies.</p>
<p>So execute the following command from the <code>testing-library-demo</code> folder:</p>
<pre><code class="lang-js">yarn add @testing-library/jest-dom@<span class="hljs-number">5.16</span><span class="hljs-number">.5</span> @testing-library/react@<span class="hljs-number">13.4</span><span class="hljs-number">.0</span> @testing-library/user-event@<span class="hljs-number">14.4</span><span class="hljs-number">.3</span> jest@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> jest-environment-jsdom@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> vitest@<span class="hljs-number">0.25</span><span class="hljs-number">.3</span> --dev
</code></pre>
<p>or with npm:</p>
<pre><code class="lang-js">npm install @testing-library/jest-dom@<span class="hljs-number">5.16</span><span class="hljs-number">.5</span> @testing-library/react@<span class="hljs-number">13.4</span><span class="hljs-number">.0</span> @testing-library/user-event@<span class="hljs-number">14.4</span><span class="hljs-number">.3</span> jest@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> jest-environment-jsdom@<span class="hljs-number">29.3</span><span class="hljs-number">.1</span> vitest@<span class="hljs-number">0.25</span><span class="hljs-number">.3</span> --save-dev
</code></pre>
<p>I'm mentioning versions here for each package which are the latest versions at the time of writing this tutorial. So even if there is a newer breaking version release that happens for any of the packages in the future, your code will not break.</p>
<p>Here, we're installing the <code>jest-environment-jsdom</code> library because we will be running tests in the node environment. But we're testing browser interactions through the DOM – so to inform Jest about that, we need to add this library.</p>
<p>The <code>@testing-library/jest-dom</code> library is required because it contains assertions like <code>toBeInTheDocument</code>, <code>toHaveBeenCalled</code>, and others which make it easy to test for DOM elements, which you will see later in this tutorial.</p>
<p>We have also added the <code>vitest</code> package which is only required when you're using Vite for the application.</p>
<p>You don't need it if you're using <code>create-react-app</code> or your own webpack configuration.</p>
<p>Now that we have installed the required packages, let's add a script in the <code>package.json</code> file to run the tests.</p>
<p>Open the <code>package.json</code> file and add the <code>test</code> script inside it like this:</p>
<pre><code class="lang-js"><span class="hljs-string">"test"</span>: <span class="hljs-string">"vitest"</span>
</code></pre>
<p>Your <code>package.json</code> file will look like this now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/5_package_json.png" alt="Image" width="600" height="400" loading="lazy">
<em>Package.json file preview</em></p>
<p>If you're not using <code>vite</code> for creating the React app, then you will be using the following test script:</p>
<pre><code class="lang-js"><span class="hljs-string">"test"</span>: <span class="hljs-string">"jest --watch"</span>
</code></pre>
<p>Now, create a new file in the root of your project (<code>testing-library-demo</code>) with the name <code>setupTests.js</code> and add the following code inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom"</span>;
</code></pre>
<p>Now, open the <code>vite.config.js</code> file and add a new <code>test</code> object as shown in the below screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/9_vite_config.png" alt="Image" width="600" height="400" loading="lazy">
<em>vite.config.js file configuration</em></p>
<h2 id="heading-how-to-create-the-ui-for-testing">How to Create the UI for Testing</h2>
<p>Before writing tests, we need to have some components to test.</p>
<p>So let's create a simple registration page with some checkboxes, input fields, select dropdown, and buttons so we can write test cases for it.</p>
<p>We will use <a target="_blank" href="https://react-bootstrap.github.io/">react-bootstrap</a> to create the UI elements so we don't have to write all the CSS from scratch.</p>
<p>Install <code>bootstrap</code> and <code>react-bootstrap</code> by executing the following command from the terminal:</p>
<pre><code class="lang-js">yarn add bootstrap@<span class="hljs-number">5.2</span><span class="hljs-number">.3</span> react-bootstrap@<span class="hljs-number">2.6</span><span class="hljs-number">.0</span> react-select@<span class="hljs-number">5.6</span><span class="hljs-number">.1</span>
</code></pre>
<p>or with npm:</p>
<pre><code class="lang-js">npm install bootstrap@<span class="hljs-number">5.2</span><span class="hljs-number">.3</span> react-bootstrap@<span class="hljs-number">2.6</span><span class="hljs-number">.0</span> react-select@<span class="hljs-number">5.6</span><span class="hljs-number">.1</span>
</code></pre>
<p>Bootstrap provides a base CSS which we need for the UI to look nice, so we're also installing Bootstrap along with react-bootstrap.</p>
<p>Once installed, open <code>src/main.jsx</code> and add an import for the Bootstrap CSS file before any of your other CSS files as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"bootstrap/dist/css/bootstrap.min.css"</span>;
</code></pre>
<p>Your <code>src/main.jsx</code> file will look like this now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/6_bootstrap_css.png" alt="Image" width="600" height="400" loading="lazy">
<em>bootstrap css imported</em></p>
<p>We don't need the <code>index.css</code> and <code>App.css</code> files so you can delete them.</p>
<p>Now, create a <code>components</code> folder inside the <code>src</code> folder and create a <code>register</code> folder inside the <code>components</code> folder. Inside the <code>register</code> folder, create <code>Register.jsx</code> and <code>register.css</code> files.</p>
<p>So your <code>Register.js</code> file path will be <code>src/components/register/Register.js</code>.</p>
<p>Add the content from <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo/blob/master/src/components/register/Register.jsx">this repo</a> in the <code>Register.jsx</code> file and inside <code>register.css</code> file add contents from <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo/blob/master/src/components/register/register.css">this repo</a>.</p>
<p>Now, open the <code>App.jsx</code> file and add the following contents inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Register"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</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 application by executing the <code>yarn run dev</code> or <code>npm run dev</code> command, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/7_register_page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Registration page</em></p>
<p>This tutorial is focused on the testing library, so I'm not going to explain the code from the <code>Register.js</code> file as it's basic React code. But If you're not familiar with React hooks, you can check out <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?sk=89baff89ec8bc637e7c13b7554904e54">this article</a> to understand it better.</p>
<p>Also, instead of managing the state and onChange handler yourself, you can use the very popular <a target="_blank" href="https://react-hook-form.com/">react-hook-form</a> library.</p>
<p>It also allows you to add validations to your code without writing much code. Check out <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-forms-in-react-using-react-hook-form/">this article</a> if you want to learn about it in detail.</p>
<p>Now, we're all set to write unit test cases, so let's get started.</p>
<h2 id="heading-how-to-write-unit-test-cases">How to Write Unit Test Cases</h2>
<p>Before writing test cases, you should be aware of the different queries which you can make to access elements on the page.</p>
<p>The Testing Library provides a set of queries which you can see in the below screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/8_queries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing getBy, queryBy, findBy, getAllBy, queryAllBy, and findAllBy queries. (<a target="_blank" href="https://testing-library.com/docs/queries/about">Source</a>)</em></p>
<p>To summarise:</p>
<ul>
<li>To select a single DOM element, you can use the <code>getBy</code>, <code>findBy</code>, or <code>queryBy</code> query</li>
<li>To select multiple DOM elements, you can use the <code>getAllBy</code>, <code>findAllBy</code> or <code>queryAllBy</code> query</li>
<li><code>getBy</code> and <code>findBy</code> return an error if there is no match or more than one match</li>
<li><code>queryBy</code> returns null if there is no match and returns an error if there is more than one match</li>
<li><code>findBy</code> works well with asynchronous code but not with <code>getBy</code> and <code>queryBy</code></li>
<li><code>getAllBy</code> returns an error if there is no match and returns an array of matches for one or more than one match</li>
<li><code>findAllBy</code> returns an error if there is no match and returns an array of matches for one or more than one match</li>
<li><code>queryAllBy</code> returns an empty array for no match and returns an array of matches for one or more than one match</li>
</ul>
<p>So if you don't want your test to fail if the element is not displayed on the UI, then always use <code>queryBy</code> or <code>queryAllBy</code>.</p>
<p>In other words, only use the <code>queryBy</code> or <code>queryAllBy</code> queries for asserting that an element cannot be found or is hidden.</p>
<p>Now that you're familiar with query methods, let's start writing test cases for the <code>Register</code> component.</p>
<p>Create a new <code>register.test.jsx</code> file in the <code>src/components/register</code> folder with the following content inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./Register"</span>;

describe(<span class="hljs-string">"Register component"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>);
    expect(element).toBeInTheDocument();
  });
});
</code></pre>
<p>Note that we're using Vite so the filename has to end with the <code>.jsx</code> extension even for test files. If you're not using vite then you can end the filename with the <code>.js</code> extension.</p>
<p>Now, if you execute the <code>npm run test</code> or <code>yarn run test</code> command you will see that the test passes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/1_test_result.png" alt="Image" width="600" height="400" loading="lazy">
<em>one test passed</em></p>
<p>In the above code, we're first rendering the <code>Register</code> component using the <code>render</code> method provided by the testing library.</p>
<p>As we have an h1 element with <code>Register</code> text in the <code>Register</code> component, we're using the <code>screen.getByRole</code> method to get the DOM element of the role <code>heading</code>.</p>
<p>If you don't know what role to use in the <code>getByRole</code> method, then you can use some random name and the testing library will show you all the available roles for each DOM element for that component as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/10_role.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Seeing the DOM structure of UI elements</em></p>
<p>Once we get that element using the <code>getByRole</code> method, then we're making an assertion to check if that element exists in the DOM using:</p>
<pre><code class="lang-js">expect(element).toBeInTheDocument();
</code></pre>
<p>You can see a list of all available <code>getBy</code>,<code>findBy</code> or <code>queryBy</code> methods by adding a dot after <code>screen</code> like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/11_query_methods.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Methods provided by screen object</em></p>
<p>Now, we have added one test to check if the <code>Register</code> component is getting rendered correctly or not.</p>
<p>Let's write some more tests.</p>
<p>If you run the application by running the <code>yarn dev</code> command, you will see that, once you click on the <code>Register</code> button without filling out all the details, you get an error message as shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/12_error_message.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Error message display on submitting form without entering data</em></p>
<p>So now, we need to test the same by writing a test case.</p>
<p>For that, we can use <code>userEvent</code> from the <code>@testing-library/user-event</code> package which we've already installed.</p>
<p>Now, add a new test in your <code>register.test.jsx</code> file as shown below:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    userEvent.click(buttonElement);
});
</code></pre>
<p>Your <code>register.test.jsx</code> file will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/13_new_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>New test added for testing error message display</em></p>
<p>So we're triggering the click event for the <code>Register</code> button in the above code.</p>
<p>Now, we need to find the element with the error message so we can add assertions for it in the test.</p>
<p>The error message is actually an <code>Alert</code> component from <code>react-bootstrap</code> which is not visible initially. It's only displayed when we submit the form without filling in all the data.</p>
<p>In such a case, we can call the <code>screen.debug</code> method to see the structure of the DOM at that moment when we trigger the click event.</p>
<p>So change the test case as shown below:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    userEvent.click(buttonElement);
    screen.debug();
});
</code></pre>
<p>Note that we have added <code>screen.debug</code> at the end of the test.</p>
<p>Now, if you run the <code>yarn run test</code> or <code>npm run test</code>, you will see the following DOM structure:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/14_debug_output.png" alt="Image" width="600" height="400" loading="lazy">
<em>DOM structure when after submitting the Form</em></p>
<p>As you can see from the screenshot, you directly see the name input label inside the form tag after the <code>Register</code> heading.</p>
<p>So we're not able to see the error message even if we have triggered the click event for the button.</p>
<p>This is because it takes some time to execute the validation code from the <code>handleFormSubmit</code> method. Before that we're only using the <code>screen.debug</code> method so we don't see the error message.</p>
<p>So to fix this, we can wait using async/await.</p>
<p>So declare the test function as <code>async</code> and before the <code>userEvent.click(buttonElement)</code> add an <code>await</code> keyword like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/15_await_event.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added async/await</em></p>
<p>Now, if you check the console, you will be able to see the text <code>All the fields are required.</code> inside a div with the role <code>alert</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/error_message_dom.png" alt="Image" width="600" height="400" loading="lazy">
<em>Error message getting displayed in DOM structure</em></p>
<p>So we can use it in our assertion like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
expect(alertElement).toBeInTheDocument();
</code></pre>
<p>And now, you can see that the second test is also successful.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/16_success_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>test passed</em></p>
<p>Some points to note:</p>
<ul>
<li>Always remember to remove the <code>screen.debug</code> statement once you're done with your assertions, and never keep it in your code.</li>
<li>Always add an <code>await</code> keyword before triggering any event using <code>userEvent</code> as you may not know when the action will be completed.</li>
</ul>
<h2 id="heading-lets-write-some-more-tests">Let's Write Some More Tests</h2>
<p>Now that we're done with adding these two tests, we can add one more test to check if there is no error when the page is loaded like this:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
});
</code></pre>
<p>Here, instead of using this:</p>
<pre><code class="lang-js">expect(alertElement).toBeInTheDocument();
</code></pre>
<p>we're using this:</p>
<pre><code class="lang-js">expect(alertElement).not.toBeInTheDocument();
</code></pre>
<p>Because we want the alert element to be <strong>not</strong> present on the component load.</p>
<p>But if you check the console, you will see that the test is failing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/17_failed_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed test when using getByRole</em></p>
<p>So, the test is not failing because of our assertion. Rather, it's failing because it can't find an element with role <code>alert</code> on page load which is expected, as there will not be any error on page load.</p>
<p>But how we can make the test pass?</p>
<p>If you remember from the list of queries in the screenshot shown before:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/8_queries-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing getBy, queryBy, findBy, getAllBy, queryAllBy, and findAllBy queries.</em></p>
<p>The <code>getBy</code> method throws an error if it does not find the matching element. So instead of using <code>getBy</code> we need to use <code>queryBy</code>. It does the same thing but it does not throw an error when there is no matching element.</p>
<p>So let's modify our test case to the below code:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.queryByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
});
</code></pre>
<p>Now, if you check the console, you will see that the test passes successfully.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/18_test_passed_query.png" alt="Image" width="600" height="400" loading="lazy">
<em>Passed test when using queryByRole</em></p>
<p>Now, let's write a test for successful registration when we fill out all the required fields.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should show success message when the registration is successful."</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>);
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
});
</code></pre>
<p>Now if you see the console, you will see that the test passes successfully.</p>
<p>Let's add a subheading to the registration page and see what happens when we run the tests again.</p>
<p>Add the following heading inside the <code>Form</code> tag in the <code>Register.jsx</code> file:</p>
<pre><code class="lang-js">&lt;h6 className=<span class="hljs-string">"subtitle"</span>&gt;
   Please enter your details below to register yourself.
&lt;/h6&gt;
</code></pre>
<p>So your code will now look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/20_subtitle.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added new subheading</em></p>
<p>Now, if you run the tests again, you will see that one test fails:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/21_failed_multiple.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed test due to multiple headings on the page</em></p>
<p>The test failed because in the first test we're finding the <code>Register</code> heading text as shown below:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">"heading"</span>)
</code></pre>
<p>And as you know, <code>getBy</code> returns an error when you have more than one match. </p>
<p>Here, we have two headings on the <code>Register</code> component so the test failed.</p>
<p>So how can we fix it?</p>
<p>To fix it we need to identify how to accurately select elements while writing tests.</p>
<p>I have seen many developers changing the HTML structure by adding some <code>testid</code> so they can get the test passed like this:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByTestId(<span class="hljs-string">"title"</span>);
    expect(element).toBeInTheDocument();
});
</code></pre>
<p>Assuming you added an extra <code>data-testid</code> attribute to your JSX like this:</p>
<pre><code class="lang-js">&lt;h2 className=<span class="hljs-string">"title"</span> data-testid=<span class="hljs-string">"title"</span>&gt;
     Register
&lt;/h2&gt;
</code></pre>
<p>This will work and make your all tests pass. But this is not the correct way.</p>
<p>Just to make your test pass, <strong>you should not change your JSX by adding some extra <code>testid</code> or <code>class</code>.</strong></p>
<p>Instead, you should <strong>always try to use methods provided by <code>screen</code></strong> to make an accurate selection of DOM elements.</p>
<p>So now the question is how to make an accurate selection.</p>
<p>The <code>getByRole</code> method accepts optional options which you can use like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">2</span> });
</code></pre>
<p>As our main <code>Register</code> heading is a <code>h2</code> heading, we specifically said to select <code>level 2</code> heading.</p>
<p>Now, if you update the first test case, you will see that all the tests are passing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/22_fixed_failing_test.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test passed by adding more specific query for heading</em></p>
<p>Now, let's add another test for testing the subheading.</p>
<p>As the subheading is of level 6, you can query it like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, { <span class="hljs-attr">level</span>: <span class="hljs-number">6</span> });
</code></pre>
<p>This will work, but there is another way we can target that element.</p>
<p>For that, you can install the <a target="_blank" href="https://chrome.google.com/webstore/detail/testing-playground/hejbmebodbijjdhflfknehhcgaklhano?hl=en">testing playground</a> Chrome browser extension.</p>
<p>Once it's installed, follow the below steps:</p>
<ul>
<li>open your Chrome dev tools using Ctrl + Alt + I or Cmd + Option + I (Mac)</li>
<li>select the <code>Testing Playground</code> tab</li>
<li>Click the cursor pointer and select the subheading of the <code>Register</code> component as shown below:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/23_accurate_subheading.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing Playground extension demo</em></p>
<p>As you can see, you will get the accurate DOM element query which you can use in your test like this:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">'heading'</span>, {
  <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
})
</code></pre>
<p>So you can write your test like this:</p>
<pre><code class="lang-js"> it(<span class="hljs-string">"should test for presence of subheading in the component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
    });
    expect(element).toBeInTheDocument();
 });
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/24_all_passed.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test result</em></p>
<p>Writing a test case for subheading is not necessary, because it does not affect the component behavior even if you don't test that. But just to show you how your tests will break for multiple elements, I have added that element on the UI along with its test case.</p>
<p>The <code>Testing Playground</code> Chrome extension is really useful to find out the exact matching query for any of the UI elements.</p>
<p>So instead of using the <code>screen.debug</code> method to see the DOM structure, you can use this Chrome extension to find out the role and other information for all the displayed elements as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/25_extension_demo.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Finding out specific query using testing playground</em></p>
<p>As you can see, you can get any element by role, by placeholder text, or by label text with the methods provided by <code>screen</code>.</p>
<p>Now that you're aware of the more specific query selectors, let's update other test cases to use the specific selectors.</p>
<p>Wherever we're using just <code>screen.getByRole("button")</code>, replace it with the following:</p>
<pre><code class="lang-js">screen.getByRole(<span class="hljs-string">"button"</span>, {
  <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
})
</code></pre>
<p>So now, if later someone adds another button in the same component, your test will not fail.</p>
<p>Your final <code>register.test.jsx</code> file will look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> userEvent <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/user-event"</span>;
<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./Register"</span>;

describe(<span class="hljs-string">"Register component"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should render Register component correctly"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">level</span>: <span class="hljs-number">2</span>
    });
    expect(element).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should test for presence of subheading in the component"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> element = screen.getByRole(<span class="hljs-string">"heading"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/please enter your details below to register yourself\./i</span>
    });
    expect(element).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should show error message when all the fields are not entered"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
    });
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
  });

  it(<span class="hljs-string">"should not show any error message when the component is loaded"</span>, <span class="hljs-function">() =&gt;</span> {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> alertElement = screen.queryByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).not.toBeInTheDocument();
  });

  it(<span class="hljs-string">"should show success message when the registration is successful."</span>, <span class="hljs-keyword">async</span> () =&gt; {
    render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Register</span> /&gt;</span></span>);
    <span class="hljs-keyword">const</span> buttonElement = screen.getByRole(<span class="hljs-string">"button"</span>, {
      <span class="hljs-attr">name</span>: <span class="hljs-regexp">/register/i</span>
    });
    <span class="hljs-keyword">await</span> userEvent.click(buttonElement);
    <span class="hljs-keyword">const</span> alertElement = screen.getByRole(<span class="hljs-string">"alert"</span>);
    expect(alertElement).toBeInTheDocument();
  });
});
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>React Testing library is amazing and has become a very popular tool with which to test React applications.</p>
<p>Just remember that unlike <a target="_blank" href="https://enzymejs.github.io/enzyme/">enzyme testing library</a>, you should not test for state changes when using React Testing Library.</p>
<p>So we have not written test cases to check if the state correctly changes after the user types some text in the <code>name</code>, <code>email</code>, or <code>password</code> fields.</p>
<p>In React Testing Library you check the behavior of DOM when the user clicks on a button or submits a form and so on instead of testing the internal state of the component.</p>
<h3 id="heading-thanks-for-reading">Thanks for Reading!</h3>
<p>You can find the complete source code for this tutorial in <a target="_blank" href="https://github.com/myogeshchavan97/testing-library-demo">this repository</a>.</p>
<p>If you want to become the best MERN stack developer (full stack developer), then do check out <a target="_blank" href="https://online-elearning-platform.netlify.app/">my course</a>.</p>
<ul>
<li>This is a pre-recorded video course that will be constantly updated for any future changes.</li>
<li>In this course, you will learn how to create React and Node.js applications from scratch and build an amazing online learning platform.</li>
<li>After learning through this course, you will be able to build any MERN stack application confidently and easily.</li>
<li>There is a separate section in this course, where you will learn how to test your entire React application using React testing library and jest.</li>
</ul>
<p>So do check out this amazing course.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Forms in React using react-hook-form ]]>
                </title>
                <description>
                    <![CDATA[ Creating forms in React is a complex task. It involves handling all the input states and their changes and validating that input when the form gets submitted. For simple forms, things are generally manageable. But as your form gets more complex and y... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-forms-in-react-using-react-hook-form/</link>
                <guid isPermaLink="false">66bc5510da80a491ea5a5f3d</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Thu, 27 Oct 2022 19:47:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/cover.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Creating forms in React is a complex task. It involves handling all the input states and their changes and validating that input when the form gets submitted.</p>
<p>For simple forms, things are generally manageable. But as your form gets more complex and you need to add various validations, it becomes a complicated task.</p>
<p>So instead of manually writing all of the code and handling complex forms with validation logic, we can use the most popular React library for this, <a target="_blank" href="https://react-hook-form.com/">react-hook-form</a>.</p>
<p>It's the most popular React library for creating forms compared to <a target="_blank" href="https://formik.org/">formik</a>, <a target="_blank" href="https://final-form.org/react/">react final form</a>, and others, and I use it for all my client projects.</p>
<p>In this article, we will explore how to use the <a target="_blank" href="https://react-hook-form.com/">react-hook-form</a> library in detail.</p>
<p>So let's get started.</p>
<h2 id="heading-why-the-react-hook-form-library-is-the-most-popular-form-library-in-react">Why the react-hook-form Library is the Most Popular Form Library in React</h2>
<p>Following are some of the reasons why <code>react-hook-form</code> is a popular choice for creating React forms.</p>
<ul>
<li>The number of re-renders in the application is smaller compared to the alternatives because it uses refs instead of state.</li>
<li>The amount of code you have to write is less as compared to <code>formik</code>, <code>react-final-form</code> and other alternatives.</li>
<li><code>react-hook-form</code> integrates well with the <code>yup</code> library for schema validation so you can combine your own validation schemas.</li>
<li>Mounting time is shorter compared to other alternatives.</li>
</ul>
<p>Check out the <a target="_blank" href="https://react-hook-form.com/">react-hook-form</a> website for more detailed comparison.</p>
<h2 id="heading-how-to-create-a-form-without-using-a-library">How to Create a Form Without Using a Library</h2>
<p>Before creating a form using the <code>react-hook-form</code> library, let's create a simple form without using any library.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [state, setState] = useState({
    <span class="hljs-attr">email</span>: <span class="hljs-string">""</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>
  });

  <span class="hljs-keyword">const</span> handleInputChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { name, value } = event.target;
    setState(<span class="hljs-function">(<span class="hljs-params">prevProps</span>) =&gt;</span> ({
      ...prevProps,
      [name]: value
    }));
  };

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    <span class="hljs-built_in">console</span>.log(state);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">name</span>=<span class="hljs-string">"email"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{state.email}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password<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">"password"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{state.password}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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>Login<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">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/login-form-zird0r?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>In the above code, we have only two input fields, namely <code>email</code> and <code>password</code> and a submit button.</p>
<p>Each input field has a <code>value</code> and <code>onChange</code> handler added so we can update the state based on the user's input.</p>
<p>Also, we have added a <code>handleSubmit</code> method which displays the data entered in the form to the console.</p>
<p>This looks fine. But what if we need to add validations like required field validation, minimum length validation, password validation, email field validation and also display the corresponding error messages?</p>
<p>The code will become more complex and lengthy as the number of input fields and their validations increases.</p>
<h2 id="heading-how-to-install-react-hook-form">How to Install react-hook-form</h2>
<p>Displaying forms is a very common requirement in any application. </p>
<p>So let’s learn why and how to use react-hook-form. For that, we'll create a new React application.</p>
<p>Create a new React project by running the following command from the terminal:</p>
<pre><code class="lang-js">create-react-app demo-react-hook-form
</code></pre>
<p>Once the project is created, delete all files from the <code>src</code> folder and create new <code>index.js</code> and <code>styles.css</code> files inside the <code>src</code> folder.</p>
<p>To install the <code>react-hook-form</code> library, execute the following command from the terminal:</p>
<pre><code class="lang-js">npm install react-hook-form@<span class="hljs-number">7.38</span><span class="hljs-number">.0</span>

OR

yarn add react-hook-form@<span class="hljs-number">7.38</span><span class="hljs-number">.0</span>
</code></pre>
<p>Here, we're installing version <code>7.38.0</code> of the <code>react-hook-form</code> library which is the latest version at the time of writing this article.</p>
<h2 id="heading-how-to-create-initial-pages">How to Create Initial Pages</h2>
<p>Open the <code>src/index.js</code> file and add the following content inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
</code></pre>
<p>Note that the above code is using React version 18+ syntax for rendering the app.</p>
<p>If you're using React version less than 18 (which you can confirm from the <code>package.json</code> file), then add the following code in your <code>src/index.js</code> file.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> 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">App</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
</code></pre>
<p>Now, open the <code>src/styles.css</code> file and add the content from <a target="_blank" href="https://gist.github.com/myogeshchavan97/2e0b00d38f8f927799d8180906e9dde3">here</a> inside it.</p>
<p>Now, create a new file called <code>App.js</code> inside the <code>src</code> folder with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">name</span>=<span class="hljs-string">"email"</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password<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">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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>Login<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">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here, we have just added the email and password fields to the form.</p>
<h2 id="heading-how-to-create-a-basic-form-with-react-hook-form">How to Create a Basic Form with react-hook-form</h2>
<p>The <code>react-hook-form</code> library provides a <code>useForm</code> hook which we can use to work with forms.</p>
<p>Import the <code>useForm</code> hook like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-hook-form'</span>;
</code></pre>
<p>You can use the <code>useForm</code> hook like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> {
  register,
  handleSubmit,
  <span class="hljs-attr">formState</span>: { errors },
} = useForm();
</code></pre>
<p>Here,</p>
<ul>
<li><code>register</code> is a function provided by the <code>useForm</code> hook. We can assign it to each input field so that the <code>react-hook-form</code> can track the changes for the input field value</li>
<li><code>handleSubmit</code> is the function we can call when the form is submitted</li>
<li><code>errors</code> is a nested property in the <code>formState</code> object which will contain the validation errors, if any</li>
</ul>
<p>Now, replace the contents of the <code>App.js</code> file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">name</span>=<span class="hljs-string">"email"</span> {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password<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">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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>Login<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">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the above code, we have added a register function to each input field that we got from the <code>useForm</code> hook by passing a unique name to each <code>register</code> function like this:</p>
<pre><code class="lang-js">{...register(<span class="hljs-string">"email"</span>)}
</code></pre>
<p>We're using the spread operator so <code>react-hook-form</code> will spread out all the required event handlers like <code>onChange</code>, <code>onBlur</code>, and other props for that input field.</p>
<p>If you add a <code>console.log({ ...register("email") });</code> inside the component, you will see what it returns as can be seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/register_output.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We also added the <code>onSubmit</code> function which is passed to the <code>handleSubmit</code> method like this:</p>
<pre><code class="lang-js">&lt;form onSubmit={handleSubmit(onSubmit)}&gt;
...
</code></pre>
<p>Note that, you need to pass a unique name to the <code>register</code> function added for each input field so <code>react-hook-form</code> can track the changing data.</p>
<p>When we submit the form, the <code>handleSubmit</code> function will handle the form submission. It will send the user entered data to the <code>onSubmit</code> function where we're logging the user data to the console.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {  
 <span class="hljs-built_in">console</span>.log(data);
};
</code></pre>
<p>Now, start the application by running the <code>npm start</code>  or <code>yarn start</code> command and you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/login_logs-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/login-form-forked-9so04x?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>As you can see, when we submit the form, the details entered by the user are displayed in the console.</p>
<p>Also, as compared to the code without <code>react-hook-form</code> (which we saw at the start of this article in this <a target="_blank" href="https://codesandbox.io/s/login-form-zird0r?file=/src/App.js">Code Sandbox demo</a>), this code is much simpler. </p>
<p>This is because we don’t have to add the <code>value</code> and <code>onChange</code> handler for each input field and there is no need to manage the application state ourselves.</p>
<h2 id="heading-how-to-add-validations-to-the-form">How to Add Validations to the Form</h2>
<p>Now, let’s add the required field and minimum length validation to the input fields.</p>
<p>To add validation we can pass an object to the <code>register</code> function as a second parameter like this:</p>
<pre><code class="lang-js">&lt;input
  type=<span class="hljs-string">"text"</span>
  name=<span class="hljs-string">"email"</span>
  {...register(<span class="hljs-string">"email"</span>, {
    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
  })}
/&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
  <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
  {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
    <span class="hljs-attr">required:</span> <span class="hljs-attr">true</span>,
    <span class="hljs-attr">minLength:</span> <span class="hljs-attr">6</span>
  })}
/&gt;</span></span>
</code></pre>
<p>Here, for the email field, we're specifying required field validation. For the password field we're specifying the required field and minimum 6 character length validation.</p>
<p>When the validation fails, the <code>errors</code> object coming from the <code>useForm</code> hook will be populated with the fields for which the validation failed.</p>
<p>So we will use that <code>errors</code> object to display custom error messages.</p>
<p>Open the <code>App.js</code> file and replace its contents with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">name</span>=<span class="hljs-string">"email"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
              <span class="hljs-attr">required:</span> <span class="hljs-attr">true</span>,
              <span class="hljs-attr">pattern:</span> /^[^@ ]+@[^@ ]+\<span class="hljs-attr">.</span>[^@ <span class="hljs-attr">.</span>]{<span class="hljs-attr">2</span>,}$/
            })}
          /&gt;</span>
          {errors.email &amp;&amp; errors.email.type === "required" &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          )}
          {errors.email &amp;&amp; errors.email.type === "pattern" &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is not valid.<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> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password<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">"password"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
              <span class="hljs-attr">required:</span> <span class="hljs-attr">true</span>,
              <span class="hljs-attr">minLength:</span> <span class="hljs-attr">6</span>
            })}
          /&gt;</span>
          {errors.password &amp;&amp; errors.password.type === "required" &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Password is required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          )}
          {errors.password &amp;&amp; errors.password.type === "minLength" &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>
              Password should be at-least 6 characters.
            <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> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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>Login<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">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>If you check the application now, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/basic_validation-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/login-form-with-validations-6388wx?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>As you can see, we're getting instant validation errors for each input field once we submit the form and then try to enter the values in the input fields.</p>
<p>If there is any error for any of the input field, the <code>errors</code> object will be populated with the type of error which we're using to display our own custom error message like this:</p>
<pre><code class="lang-js">{errors.email &amp;&amp; errors.email.type === <span class="hljs-string">"required"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
{errors.email &amp;&amp; errors.email.type === <span class="hljs-string">"pattern"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is not valid.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p>Here, based on the type of error, we're displaying different error messages.</p>
<p>Using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining">ES11 optional chaining operator</a>, you can further simplify the above code like this:</p>
<pre><code class="lang-js">{errors.email?.type === <span class="hljs-string">"required"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
{errors.email?.type === <span class="hljs-string">"pattern"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Email is not valid.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p>In the similar way, we have added the password field validation.</p>
<p>Also, as you can see, each input field is automatically focused when we submit the form if there is any validation error for that input field.</p>
<p>Also, the form is not submitted as long as there is a validation error. If you check the browser console, you will see that the <code>console.log</code> statement is only printed if the form is valid and there are no errors.</p>
<p>So using <code>react-hook-form</code> reduced the amount of code that we had to write. The validation is also responsive, so once the field becomes valid, the error message goes away instantly.</p>
<p>But as the number of validations for each field increases, the conditional checks and error message code will still increase. So we can further refactor the code to make it even simpler.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">name</span>=<span class="hljs-string">"email"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Email</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>",
              <span class="hljs-attr">pattern:</span> {
                <span class="hljs-attr">value:</span> /^[^@ ]+@[^@ ]+\<span class="hljs-attr">.</span>[^@ <span class="hljs-attr">.</span>]{<span class="hljs-attr">2</span>,}$/,
                <span class="hljs-attr">message:</span> "<span class="hljs-attr">Email</span> <span class="hljs-attr">is</span> <span class="hljs-attr">not</span> <span class="hljs-attr">valid.</span>"
              }
            })}
          /&gt;</span>
          {errors.email &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.email.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password<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">"password"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>",
              <span class="hljs-attr">minLength:</span> {
                <span class="hljs-attr">value:</span> <span class="hljs-attr">6</span>,
                <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">should</span> <span class="hljs-attr">be</span> <span class="hljs-attr">at-least</span> <span class="hljs-attr">6</span> <span class="hljs-attr">characters.</span>"
              }
            })}
          /&gt;</span>
          {errors.password &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.password.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          )}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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>Login<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">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, we have changed the email and password validation code.</p>
<p>For the email input field, we changed this previous code:</p>
<pre><code class="lang-js"> {...register(<span class="hljs-string">"email"</span>, {
     <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">pattern</span>: <span class="hljs-regexp">/^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/</span>
 })}
</code></pre>
<p>to the below code:</p>
<pre><code class="lang-js">{...register(<span class="hljs-string">"email"</span>, {
    <span class="hljs-attr">required</span>: <span class="hljs-string">"Email is required."</span>,
    <span class="hljs-attr">pattern</span>: {
        <span class="hljs-attr">value</span>: <span class="hljs-regexp">/^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/</span>,
        message: <span class="hljs-string">"Email is not valid."</span>
    }
})}
</code></pre>
<p>Here, we’ve directly provided the error message we want to display while adding the validation itself.</p>
<p>So we no longer need to add extra checks for each validation. We are displaying the error message using the <code>message</code> property available inside the <code>errors</code> object for each input field like this:</p>
<pre><code class="lang-js">{errors.email &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.email.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>}
</code></pre>
<p>So by doing it this way, the code is further simplified which makes it easy to add extra validations in the future.</p>
<p>Note that, if there are validation errors, the onSubmit handler will not be executed and the corresponding input field will automatically be focused (which is a good thing).</p>
<p>Here's an updated <a target="_blank" href="https://codesandbox.io/s/login-form-with-validations-simplified-7o4y0k?file=/src/App.js">Code Sandbox demo</a>.</p>
<h2 id="heading-how-to-add-a-multiple-validations">How to Add a Multiple Validations</h2>
<p>You can even provide multiple validations for the input field by adding a <code>validate</code> object. This is useful if you need to perform complex validations like this:</p>
<pre><code class="lang-js"> &lt;input
    type=<span class="hljs-string">"password"</span>
    name=<span class="hljs-string">"password"</span>
    {...register(<span class="hljs-string">"password"</span>, {
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">validate</span>: {
            <span class="hljs-attr">checkLength</span>: <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> value.length &gt;= <span class="hljs-number">6</span>,
            <span class="hljs-attr">matchPattern</span>: <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span>
            <span class="hljs-regexp">/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s)(?=.*[!@#$*])/</span>.test(
                value
            )
        }
    })}
/&gt;
</code></pre>
<p>and to display the error messages, we use it like this:</p>
<pre><code class="lang-js">{errors.password?.type === <span class="hljs-string">"required"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>Password is required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
{errors.password?.type === <span class="hljs-string">"checkLength"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>
        Password should be at-least 6 characters.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
{errors.password?.type === <span class="hljs-string">"matchPattern"</span> &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>
        Password should contain at least one uppercase letter, lowercase
letter, digit, and special symbol.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/login-form-with-validations-multiple-zyvp69?file=/src/App.js">Code Sandbox demo</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/multiple_validations.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-reset-the-form-values">How to Reset the Form Values</h2>
<p>Sometimes, we need to reset/clear the data entered by the user after some action.</p>
<p>For example, once the form is submitted, we want to show the success message and then clear the form data so the user should not re-submit the same data.</p>
<p>In such a case, we can call the <code>reset</code> function returned by the <code>useForm</code> hook to clear the form data.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { reset } = useForm();
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/reset-form-buowrs?file=/src/App.js">Code Sandbox demo</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/reset.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The <code>reset</code> function also accepts an optional object where you can pass the values you want the form data to reset:</p>
<pre><code class="lang-js">reset({
    <span class="hljs-attr">username</span>: <span class="hljs-string">"Alex"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"alex@example.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"Test@123"</span>
});
</code></pre>
<p>Here, the key username, email or password should match with the name passed to the <code>register</code> function so the respective input field will be set to the passed value.</p>
<h2 id="heading-how-to-set-initial-form-values-using-defaultvalues">How to Set Initial Form Values Using defaultValues</h2>
<p>The <a target="_blank" href="https://react-hook-form.com/api/useform/">useForm</a> hook accepts a list of options, one of which is <code>defaultValues</code>.</p>
<p>Using <code>defaultValues</code> we can set initial values for the form elements and re-set them when moving from one page to another like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { user } = props;
<span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
} = useForm({
   <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">first_name</span>: user.first_name,
      <span class="hljs-attr">last_name</span>: user.last_name
    }
});

<span class="hljs-comment">// JSX</span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">first_name</span>")}
/&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">last_name</span>")}
/&gt;</span></span>
</code></pre>
<p>In the above code, for the <code>register</code> function we've passed <code>first_name</code> as the name. This means that in the <code>defaultValues</code> we're using the same name to set the initial value.</p>
<p>So to correctly set the input value, you need to use the same name used in the <code>register</code> function for setting the initial value using <code>defaultValues</code>.</p>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/nice-khorana-80rktx?file=/src/components/FirstStep.js">Code Sandbox demo</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/retain_values.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-use-react-hook-form-with-other-libraries">How to Use react-hook-form with Other Libraries</h2>
<p>Sometimes, we might be using some external libraries like <a target="_blank" href="https://react-select.com/home">react-select</a> to allow multiple selection in a dropdown.</p>
<p>In such cases, we can't directly add the <code>register</code> function for showing the select dropdown. So If we want to add <code>react-hook-form</code> validations without writing our own code and handler function, we can use the <code>Controller</code> component from <code>react-hook-form</code> like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useForm, Controller } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> Select <span class="hljs-keyword">from</span> <span class="hljs-string">"react-select"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">const</span> departments = [
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"Computer-Science"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Computer Science"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"Physics"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Physics"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"Chemistry"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Chemistry"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"Mathematics"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Mathematics"</span> }
];

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    control,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(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">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Select Department of Interest<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Controller</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"department"</span>
            <span class="hljs-attr">control</span>=<span class="hljs-string">{control}</span>
            <span class="hljs-attr">rules</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">required:</span> <span class="hljs-attr">true</span> }}
            <span class="hljs-attr">render</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">field</span> }) =&gt;</span> (
              <span class="hljs-tag">&lt;<span class="hljs-name">Select</span> {<span class="hljs-attr">...field</span>} <span class="hljs-attr">isMulti</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{departments}</span> /&gt;</span>
            )}
          /&gt;
          {errors.department &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>This is a required field.<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> <span class="hljs-attr">className</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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">div</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>&gt;</span></span>
  );
}
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/react-hook-form-controller-g8jxbf?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>As you can see in the above code, we're importing the <code>Controller</code> component  at the top:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useForm, Controller } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
</code></pre>
<p>and <code>control</code> from <code>useForm</code> hook like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> {
    control,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();
</code></pre>
<p>Note, we're not using the <code>register</code> function here.</p>
<p>Regular use of the <a target="_blank" href="https://react-select.com/home">react-select</a> library to allow multiple selection goes like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Select <span class="hljs-keyword">from</span> <span class="hljs-string">"react-select"</span>;

<span class="hljs-comment">// use</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">isMulti</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{options}</span> /&gt;</span></span>
</code></pre>
<p>But to use it with <code>react-hook-form</code> we need to wrap it in the <code>Controller</code> component:</p>
<pre><code class="lang-js">&lt;Controller
    name=<span class="hljs-string">"department"</span>
    control={control}
    rules={{ <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> }}
    render={<span class="hljs-function">(<span class="hljs-params">{ field }</span>) =&gt;</span> (
       <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Select</span> {<span class="hljs-attr">...field</span>} <span class="hljs-attr">isMulti</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{options}</span> /&gt;</span></span>
    )}
 /&gt;
</code></pre>
<p>Here, we have to give a unique value for the <code>name</code> prop in the <code>Controller</code>.</p>
<p>The validations are added as a part of the <code>rules</code> prop and we use the <code>render</code> prop to render the <code>Select</code> dropdown.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/controller.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-use-other-input-types-with-react-hook-form">How to Use Other Input Types with react-hook-form</h2>
<p>In this section, we'll see how to use radio buttons and checkboxes with <code>react-hook-form</code>.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Button, Form } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-bootstrap"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"email"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your email"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">your</span> <span class="hljs-attr">email</span>",
              <span class="hljs-attr">pattern:</span> {
                <span class="hljs-attr">value:</span> /^[^@ ]+@[^@ ]+\<span class="hljs-attr">.</span>[^@ <span class="hljs-attr">.</span>]{<span class="hljs-attr">2</span>,}$/,
                <span class="hljs-attr">message:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">a</span> <span class="hljs-attr">valid</span> <span class="hljs-attr">email</span>"
              }
            })}
          /&gt;</span>
          {errors.email &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.email.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"gender"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Select Gender<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Male"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"male"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">gender</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">select</span> <span class="hljs-attr">your</span> <span class="hljs-attr">gender</span>"
            })}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Female"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"female"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">gender</span>")}
          /&gt;</span>
          {errors.gender &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.gender.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"skills"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Select Your Skills<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"JavaScript"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"JavaScript"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">select</span> <span class="hljs-attr">at-least</span> <span class="hljs-attr">one</span> <span class="hljs-attr">skill</span>"
            })}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"React"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"react"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Node.js"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"nodejs"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Angular"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"angular"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          {errors.skills &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.skills.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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">variant</span>=<span class="hljs-string">"primary"</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 class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/react-hook-form-other-inputs-zm7u7f?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>In the above code, I'm using <a target="_blank" href="https://react-bootstrap.github.io/">react-bootstrap</a> to make the UI look good, so <code>Form.Check</code> is a <code>react-bootstrap</code> component.</p>
<p>The main point you need to remember is that we've not given the same names for the <code>register</code> function for a group of radio buttons and checkboxes like this:</p>
<pre><code class="lang-js">&lt;Form.Check
    type=<span class="hljs-string">"radio"</span>
    label=<span class="hljs-string">"Male"</span>
    value=<span class="hljs-string">"male"</span>
    {...register(<span class="hljs-string">"gender"</span>, {
        <span class="hljs-attr">required</span>: <span class="hljs-string">"Please select your gender"</span>
    })}
/&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
    <span class="hljs-attr">label</span>=<span class="hljs-string">"Female"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">"female"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">gender</span>")}
/&gt;</span></span>
</code></pre>
<p>In the above code, we've given <code>gender</code> as the name for both the radio buttons and <code>skills</code> as the name for all the checkboxes as shown below:</p>
<pre><code class="lang-js">&lt;Form.Check
    type=<span class="hljs-string">"checkbox"</span>
    label=<span class="hljs-string">"JavaScript"</span>
    value=<span class="hljs-string">"JavaScript"</span>
    {...register(<span class="hljs-string">"skills"</span>, {
        <span class="hljs-attr">required</span>: <span class="hljs-string">"Please select at-least one skill"</span>
    })}
/&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
    <span class="hljs-attr">label</span>=<span class="hljs-string">"React"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">"react"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
/&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
    <span class="hljs-attr">label</span>=<span class="hljs-string">"Node.js"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">"nodejs"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
/&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
    <span class="hljs-attr">label</span>=<span class="hljs-string">"Angular"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">"angular"</span>
    {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
/&gt;</span></span>
</code></pre>
<p>Also, note that the required field validation is added only for the first radio button or checkbox. Because we're using the same name, we don't need to add the same validation to each radio button or checkbox.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/radio_checkbox.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-set-initial-values-for-radio-buttons-and-checkboxes">How to Set Initial Values for Radio Buttons And Checkboxes</h2>
<p>Sometimes we may have pre-selected radio buttons or checkboxes which we need to display on page load, in such a case, we can again use the <code>defaultValues</code> option from for the <code>useForm</code> hook.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Button, Form } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-bootstrap"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">const</span> initialValues = {
  <span class="hljs-attr">gender</span>: <span class="hljs-string">"male"</span>,
  <span class="hljs-attr">skills</span>: {
    <span class="hljs-attr">JavaScript</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">react</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">nodejs</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">angular</span>: <span class="hljs-literal">false</span>
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm({
    <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">gender</span>: initialValues.gender,
      <span class="hljs-attr">skills</span>: <span class="hljs-built_in">Object</span>.keys(initialValues.skills).filter(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> initialValues.skills[item] === <span class="hljs-literal">true</span>
      )
    }
  });

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"email"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your email"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">your</span> <span class="hljs-attr">email</span>",
              <span class="hljs-attr">pattern:</span> {
                <span class="hljs-attr">value:</span> /^[^@ ]+@[^@ ]+\<span class="hljs-attr">.</span>[^@ <span class="hljs-attr">.</span>]{<span class="hljs-attr">2</span>,}$/,
                <span class="hljs-attr">message:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">a</span> <span class="hljs-attr">valid</span> <span class="hljs-attr">email</span>"
              }
            })}
          /&gt;</span>
          {errors.email &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.email.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"gender"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Select Gender<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Male"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"male"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">gender</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">select</span> <span class="hljs-attr">your</span> <span class="hljs-attr">gender</span>"
            })}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Female"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"female"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">gender</span>")}
          /&gt;</span>
          {errors.gender &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.gender.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-3"</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"skills"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>Select Your Skills<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"JavaScript"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"JavaScript"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>", {
              <span class="hljs-attr">required:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">select</span> <span class="hljs-attr">at-least</span> <span class="hljs-attr">one</span> <span class="hljs-attr">skill</span>"
            })}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"React"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"react"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Node.js"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"nodejs"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Form.Check</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Angular"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">"angular"</span>
            {<span class="hljs-attr">...register</span>("<span class="hljs-attr">skills</span>")}
          /&gt;</span>
          {errors.skills &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errors.skills.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</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">variant</span>=<span class="hljs-string">"primary"</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 class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/react-hook-form-other-inputs-initial-values-t38s9v?file=/src/App.js">Code Sandbox demo</a>.</p>
<p>In the above code, we have an <code>initialValues</code> object which contains the values we want to set on the initial page load:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> initialValues = {
  <span class="hljs-attr">gender</span>: <span class="hljs-string">"male"</span>,
  <span class="hljs-attr">skills</span>: {
    <span class="hljs-attr">JavaScript</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">react</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">nodejs</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">angular</span>: <span class="hljs-literal">false</span>
  }
};
</code></pre>
<p>As we can have multiple skills, <code>skills</code> is an object as shown above. So we want to show the radio button selected if its value is <code>male</code> and we want to show only those checkboxes selected for which the value is <code>true</code> in the <code>skills</code> object.</p>
<p>Therefore, for the <code>defaultValues</code> option, we're looping over the <code>skills</code> object using the <code>filter</code> method to find out the skills for which the value is <code>true</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> {
    register,
    handleSubmit,
    <span class="hljs-attr">formState</span>: { errors }
  } = useForm({
    <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">gender</span>: initialValues.gender,
      <span class="hljs-attr">skills</span>: <span class="hljs-built_in">Object</span>.keys(initialValues.skills).filter(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> initialValues.skills[item] === <span class="hljs-literal">true</span>
      )
    }
  });
</code></pre>
<p>As the <code>JavaScript</code> and <code>nodejs</code> values are <code>true</code>, the <code>skills</code> array after the <code>filter</code> method will become <code>["JavaScript", "nodejs"]</code> so the <code>defaultValues</code> object will look like this: </p>
<pre><code class="lang-js">useForm({
    <span class="hljs-attr">defaultValues</span>: {
        <span class="hljs-attr">gender</span>: <span class="hljs-string">'male'</span>,
        <span class="hljs-attr">skills</span>: [<span class="hljs-string">"JavaScript"</span>, <span class="hljs-string">"nodejs"</span>]
    }
});
</code></pre>
<p>Therefore, when the page is loaded, only the <code>male</code> gender and the <code>JavaScript</code> and <code>Node.js</code> skills will be selected/checked by default.</p>
<p>Note that the casing used in the <code>skills</code> object has to match with the <code>value</code> specified for the checkbox. </p>
<p>So even though the label for checkbox is <code>Node.js</code>, it's value is <code>nodejs</code> so we're using <code>nodejs</code> as the key in the <code>initialValues</code> object.</p>
<p>Below is the demo of how it looks on page load.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/default_checked.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And that's it! You've learned how to use react-hook-form to more easily build complex forms in React.</p>
<h2 id="heading-thanks-for-reading">Thanks for Reading!</h2>
<p>If you want to learn Redux in detail from scratch and build 3 apps along with the <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">complete food ordering app</a>, check out my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls</li>
<li>Build 3 different apps using Redux</li>
</ul>
<p>and much more.</p>
<p>Finally, we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p><strong>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Your Node.js Application for Free with Render ]]>
                </title>
                <description>
                    <![CDATA[ For years, Heroku has been an excellent platform to host your Full Stack applications. freeCodeCamp made heavy use of Heroku early on – as have countless open source projects.  But that may change, as Heroku is bringing its generous free tier to an e... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-nodejs-application-with-render/</link>
                <guid isPermaLink="false">66bc551660ad5c1520c166ec</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Thu, 01 Sep 2022 16:08:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/pexels-pixabay-163235--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For years, Heroku has been an excellent platform to host your Full Stack applications. freeCodeCamp made heavy use of Heroku early on – as have countless open source projects. </p>
<p>But that may change, as Heroku is bringing its generous free tier to an end.</p>
<p>You may have received email from Heroku informing you that, starting November 28, 2022, you will not be able to host any app for free on the platform, and that you will now need to purchase paid plan.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/no_free_heroku.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you want to host static websites or webapps for free, you might use <a target="_blank" href="https://www.netlify.com/">Netlify</a> as I explained in <a target="_blank" href="https://www.freecodecamp.org/news/how-to-deploy-react-router-based-app-to-netlify/">this article</a> but for backend apps. This said, there are not many free platforms that provide the same feel and ease of deployment as Heroku.</p>
<p>So in this article, we'll learn how to deploy your Node.js application with Express server on <a target="_blank" href="https://render.com/">Render</a>. It's a free alternative to Heroku with a similar easy deployment process.</p>
<p>So let's get started.</p>
<h2 id="heading-what-to-do-before-deploying-your-application">What to Do Before Deploying Your Application</h2>
<p>As you might know from your experience using Heroku, every application deployed runs on a specific port which Heroku assigns randomly. You can access it using the <code>process.env.PORT</code> variable.</p>
<p>The same is true with the Render platform.</p>
<p>So you need to make sure that, instead of providing a hardcoded port value for starting your Express server, you use the <code>process.env.PORT</code> variable like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">3030</span>;

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

app.listen(PORT, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`server started on port <span class="hljs-subst">${PORT}</span>`</span>);
});
</code></pre>
<h2 id="heading-how-to-deploy-an-app-to-render-from-a-github-repository"><strong>How to Deploy an App to Render from a GitHub Repository</strong></h2>
<p>Now, once you've made the port-related change, it's time to deploy your application.</p>
<p>I already have <a target="_blank" href="https://github.com/myogeshchavan97/github-repos-nodejs-api">this GitHub repository</a> that I will be deploying to Render. This GitHub repository code just displays the list of top repositories and the numbers of stars for each repository in JSON format.</p>
<p>So let's get started.</p>
<p><a target="_blank" href="https://render.com/">Render</a> provides various ways to sign up as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/sign_up_render.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once signed up and logged in to your account, you will see a dashboard like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/dashboard.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To deploy a Node.js application, click on the <code>New Web Service</code> button under the <code>Web Services</code> option.</p>
<p>You can also click on the <code>New +</code> button displayed in the header just before your profile picture and select <code>Web Service</code> option.</p>
<p>Once clicked, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/new_web_service.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click on the <code>Connect account</code> button displayed on the right side under the GitHub menu. Once clicked, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/install_render.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click on the <code>Configure</code> link and you can give permission to select all your GitHub repositories or only selected repositories.</p>
<p>I like to give access to only selected repositories which I currently need to deploy. So I selected the <code>Only select repositories</code> option. </p>
<p>Next, click on the <code>Select repositories</code> button displayed below the option and select the GitHub repository which you want to deploy.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/connect_github.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once selected, you will see the following screen displaying the selected repository.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/selected_repository.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click on the green <code>Install</code> button to give access to the selected repository to the Render website.</p>
<p>Once clicked, you will be redirected to your dashboard where you will see your selected repository as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/connected_repository.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, click on the <code>Connect</code> button and you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/deploy_details.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, for the <code>Name</code> field, enter the a short and simple name to identify your website.</p>
<p><strong>Note:</strong> keep the <code>Name</code> value simple because it will become your application URL once the application is deployed. So if I enter <code>github-repos</code> as the value for the <code>Name</code>, my application URL will become <a target="_blank" href="https://github-repos.onrender.com"><code>https://github-repos.onrender.com</code></a>. </p>
<p>So make sure to enter a short and meaningful value for <code>Name</code>.</p>
<p>Enter the details as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/details.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For <code>Build Command</code> enter <code>yarn</code> as the value which is equivalent to the <code>yarn install</code> command. Yarn is a package manager similar to npm but faster than npm.</p>
<p>And for the <code>Start Command</code> enter <code>node index.js</code> as the value, if your entry file is <code>index.js</code>.</p>
<p>After entering all the details, scroll down and you will see the <code>Plans</code> section where your free plan will be automatically selected. If not selected, you need to select it because we're deploying the application for free.</p>
<p>If you scroll down a bit more, you will see an <code>Advanced</code> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/advanced_options.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If your application is using any environment variables, you can enter them in the <code>Advanced</code> settings as shown below. You can also add your <code>.env</code> files so you don't need to enter them manually one by one.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/env_vars-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Note that, the <code>Auto-Deploy</code> field has default value of <code>Yes</code> – so once you push your code changes to GitHub repository, they will be automatically deployed to Render.</p>
<p>If you don't want to auto-deploy your changes on every code change pushed to your GitHub repository, you can select the <code>No</code> value from the <code>Auto-Deploy</code> dropdown.</p>
<p>Now, you can click on the the <code>Create Web Service</code> button to start the deployment process.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/10-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Wait for a while until the deployment is going on. Sometimes, you might need to refresh the page if you keep seeing the "in progress" going on for long time.</p>
<p>Once the deployment is completed, you will see your application is deployed <code>Live</code> as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can click on the deployed application URL which is displayed at the top as shown in the above screenshot. In my case, the application URL is <a target="_blank" href="https://github-repos.onrender.com/">https://github-repos.onrender.com/</a>.</p>
<p>When you're deploying the application for the first time, you might see a <code>Page is not working</code> error when you try to access your deployed site.</p>
<p>Wait for a little while and keep refreshing the page using <code>Ctrl + R</code> or <code>Cmd + R(Mac)</code>. Sometimes the Render platform takes some time to start the application as we're using a free service with limited hardware.</p>
<p>Once deployed, you will see your deployed application as shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/deployed_live.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Tip:</strong> To see the JSON as it's formatted above, you can install the <a target="_blank" href="https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa?hl=en">JSON Formatter</a> Chrome Extension.</p>
<p>As you might know, when using Heroku with a free account, your application goes to sleep mode after every 30 minutes if there are no requests coming in for the application. This means it takes some time to load the application when the next request comes.  </p>
<p>Similarly, in case of Render, your application will go in sleep mode after 15 minutes if there are no requests for the application.</p>
<h3 id="heading-thanks-for-reading"><strong>Thanks for reading!</strong></h3>
<p>You can find the complete GitHub source code for the deployed application in <a target="_blank" href="https://github.com/myogeshchavan97/github-repos-nodejs-api">this repository</a>.</p>
<p><strong>You can see the live demo of the deployed application <a target="_blank" href="https://github-repos.onrender.com/">here</a>.</strong></p>
<p>If you want to learn Redux in detail from scratch and build 3 apps along with the <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">complete food ordering app</a>, check out my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls</li>
<li>Build 3 different apps using Redux</li>
</ul>
<p>and much more.</p>
<p>Finally, we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p><strong>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Redux Middleware – What it is and How to Build it from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will explore what middleware is in Redux, why it's used, and how you can create your own middleware from scratch. So let's get started.  What Is Redux Middleware? Redux Middleware allows you to intercept every action sent to the r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-redux-middleware-and-how-to-create-one-from-scratch/</link>
                <guid isPermaLink="false">66bc5535a30f8b3984dad86e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Thu, 09 Sep 2021 16:38:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/redux_middleware.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will explore what middleware is in Redux, why it's used, and how you can create your own middleware from scratch.</p>
<p>So let's get started. </p>
<h2 id="heading-what-is-redux-middleware">What Is Redux Middleware?</h2>
<p>Redux Middleware allows you to intercept every action sent to the reducer so you can make changes to the action or cancel the action.  </p>
<p>Middleware helps you with logging, error reporting, making asynchronous requests, and a whole lot more.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>;
<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;

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

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

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

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

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

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">"DECREMENT"</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">2</span>
});
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/focused-cori-h9iwo">Code Sandbox Demo</a>.</p>
<p>If you want to understand how the above code works in a step-by-step way, check out my <a target="_blank" href="https://www.freecodecamp.org/news/redux-for-beginners/">Redux for Beginners</a> article.</p>
<p>As I explained in that article, the <code>createStore</code> function accepts three arguments:</p>
<ul>
<li>the first argument is a function that is normally known as a reducer – required argument</li>
<li>the second argument is the initial value of the state – optional argument</li>
<li>the third argument is a middleware – optional argument</li>
</ul>
<h2 id="heading-how-to-create-middleware-in-react">How to Create Middleware in React</h2>
<p>To create a middleware, we first need to import the <code>applyMiddleware</code> function from Redux like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;
</code></pre>
<p>Let's say we're creating a <code>loggerMiddleware</code>. Then to define the middleware we need to use the following syntax:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function">(<span class="hljs-params">store</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">next</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">action</span>) =&gt;</span> {
  <span class="hljs-comment">// your code</span>
};
</code></pre>
<p>The above code is equivalent to the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">store</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">next</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">action</span>) </span>{
      <span class="hljs-comment">// your code</span>
    };
  };
};
</code></pre>
<p>Once the middleware function is created, we pass it to the <code>applyMiddleware</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> middleware = applyMiddleware(loggerMiddleware);
</code></pre>
<p>And finally, we pass the middleware to the <code>createStore</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> store = createStore(reducer, middleware);
</code></pre>
<p>Even though we mentioned above that middleware is the third argument to the <code>createStore</code> function, the second argument (initial state) is optional. So based on the type of arguments, the <code>createStore</code> function automatically identifies that the passed argument is a middleware because it has the specific syntax of nested functions.</p>
<p>Here's an updated <a target="_blank" href="https://codesandbox.io/s/recursing-heyrovsky-q8zl7?file=/src/index.js">Code Sandbox Demo</a> for the above code.</p>
<p>In the above Code sandbox demo, the <code>loggerMiddleware</code> looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function">(<span class="hljs-params">store</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">next</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"action"</span>, action);
  next(action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://q8zl7.csb.app/">preview link</a> for the above Code Sandbox demo.  </p>
<p>If you check the console, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/middleware_output.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Before the action is dispatched to the store, the middleware gets executed as we can see the action logged to the console. Because we're calling the <code>next</code> function inside the <code>loggerMiddleware</code> by passing the action, the reducer will also be executed which results in the change in the store.  </p>
<p>Now, what will happen If we don't call the <code>next</code> function inside the <code>loggerMiddleware</code>?  </p>
<p>Then the action will not be sent to the reducer so the store will not be updated.  </p>
<p>If you've worked with Node.js then you might find it similar to how middleware works in Node.js.  </p>
<p>In Node.js middleware also, if we don't call the <em>next</em> function, the request will not be sent forward.</p>
<p>Here's an <a target="_blank" href="https://codesandbox.io/s/dry-dew-6ybfy?file=/src/index.js">updated Code Sandbox Demo</a> with the removed <em>next</em> function call.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function">(<span class="hljs-params">store</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">next</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"action"</span>, action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://6ybfy.csb.app/">preview link</a> for the above Code Sandbox demo.  </p>
<p>If you check the console, you will see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/middleware_removed_next.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we only get the actions logged to the console. And as the action is not forwarded to the reducer, it will not be executed – so we don't see the <code>console.log</code> from the <code>store.subscribe</code> function.  </p>
<p>As described earlier, we can modify the action from the middleware before it's sent to the reducer.  </p>
<p>Here's an <a target="_blank" href="https://codesandbox.io/s/currying-cherry-nuupf?file=/src/index.js">updated Code Sandbox Demo</a> where we're changing the payload of the action before it's sent to the reducer.</p>
<p>The code for the middleware looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loggerMiddleware = <span class="hljs-function">(<span class="hljs-params">store</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">next</span>) =&gt;</span> <span class="hljs-function">(<span class="hljs-params">action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"action"</span>, action);
  action.payload = <span class="hljs-number">3</span>;
  next(action);
};
</code></pre>
<p>Here's a <a target="_blank" href="https://nuupf.csb.app/">preview link</a> for the above Code Sandbox demo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/changed_payload.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As per the code, once the action is logged to the console, we're setting the action payload to a value of 3. So the action <code>type</code> remains the same but the <code>payload</code> is changed.  </p>
<p>So we see the state changed to 3 initially. Then again it's incremented by 3 which makes it 6. Finally it's decremented by 3 making the final state value 3.  </p>
<p>Before the action is sent to the reducer, our <code>loggerMiddleware</code> gets called where we're changing the payload value and we're always setting it to 3 before it's sent to the reducer. So based on the action type INCREMENT or DECREMENT, the reducer will always be changed by a value of 3.  </p>
<p>Even though we're changing the action in the above code, there is no issue in this case because it's a middleware and not a reducer.</p>
<blockquote>
<p>Reducers should be a pure function and we shouldn't make any changes to state and action inside the reducer. You can learn more about it in detail in my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux Course</a>.</p>
</blockquote>
<p>In the above code examples, we've created a single middleware. But you can create multiple middlewares and pass them to the <code>applyMiddleware</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> middleware = applyMiddleware(loggerMiddleware, secondMiddleware, thirdMiddleware);
</code></pre>
<p>All the middlewares mentioned in the <code>applyMiddleware</code> function will be executed one after the another.</p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for reading!</strong></h2>
<p>The content of this article is a small preview from my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>If you want to learn Redux in detail from scratch and build 3 apps along with the <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">complete food ordering app</a>, check out the <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls</li>
<li>Build 3 different apps using Redux</li>
</ul>
<p>and much more.</p>
<p>Finally, we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p><strong>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Truly Reusable React Component from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will build an app with React. And you will learn how to create a truly reusable auto-suggestion component from scratch. This application will allow a user to search for a country in a list of countries. It will display matching ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-truly-reusable-react-component-from-scratch/</link>
                <guid isPermaLink="false">66bc550ea30f8b3984dad867</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Fri, 20 Aug 2021 17:54:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/pexels-sarah-chai-7262760.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will build an app with React. And you will learn how to create a truly reusable auto-suggestion component from scratch.</p>
<p>This application will allow a user to search for a country in a list of countries. It will display matching suggestions below the input field for the country the user has entered.</p>
<p>By building this application, you will learn:</p>
<ul>
<li>How to create a reusable component</li>
<li>How to use the <code>useRef</code> hook to manage auto-suggestions</li>
<li>How to create a custom reusable hook</li>
<li>How to perform the search efficiently</li>
</ul>
<p>and much more.</p>
<p>You can find the live demo of the final application <a target="_blank" href="https://react-autosuggestion-app.netlify.app/">here</a>.</p>
<p>Below is the working demo of the auto-suggestion functionality.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/suggestion_demo.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So let's get started building the app.</p>
<h2 id="heading-set-up-the-project">Set Up the Project</h2>
<p>We will be using create-react-app to initialize the project.</p>
<p>We'll be using React Hooks syntax for creating the components. So if you're not familiar with it, check out my <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?source=friends_link&amp;sk=89baff89ec8bc637e7c13b7554904e54">article on hooks here</a>.</p>
<p>Create a new React project by executing the following command:</p>
<pre><code class="lang-js">npx create-react-app react-autosuggestion-app
</code></pre>
<p>Once you've created the project, delete all files from the <code>src</code> folder and create <code>index.js</code>, <code>App.js</code>, <code>styles.css</code> files inside the <code>src</code> folder.</p>
<p>Also create <code>components</code> and <code>custom-hooks</code> folders inside the <code>src</code> folder.</p>
<p>Install the required dependencies by running the following command from the terminal or command prompt:</p>
<pre><code class="lang-js">yarn add axios@<span class="hljs-number">0.21</span><span class="hljs-number">.1</span> lodash@<span class="hljs-number">4.17</span><span class="hljs-number">.21</span> react-bootstrap@<span class="hljs-number">1.6</span><span class="hljs-number">.1</span> bootstrap@<span class="hljs-number">5.1</span><span class="hljs-number">.0</span>
</code></pre>
<p>Once those are installed, open the <code>src/styles.css</code> file and add the contents from <a target="_blank" href="https://github.com/myogeshchavan97/react-autosuggestion-app/blob/master/src/styles.css">this file</a> inside it.</p>
<h2 id="heading-how-to-build-the-initial-pages">How to Build the Initial Pages</h2>
<p>Create a new <code>countries.json</code> file inside the <code>public</code> folder and add the contents from <a target="_blank" href="https://github.com/myogeshchavan97/react-autosuggestion-app/blob/master/public/countries.json">this file</a> inside it.</p>
<p>Create an <code>AutoComplete.js</code> file inside the <code>components</code> folder with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AutoComplete</span>(<span class="hljs-params">{ isVisible, suggestions, handleSuggestionClick }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">isVisible</span> ? '<span class="hljs-attr">show</span> <span class="hljs-attr">suggestion-box</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">suggestion-box</span>'}`}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
        {suggestions.map((country, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleSuggestionClick(country)}&gt;
            {country}
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AutoComplete;
</code></pre>
<p>In this file, we're showing the suggestions to the user once the user types something in the input textbox.</p>
<p>Create an <code>useOutsideClick.js</code> file inside the <code>custom-hooks</code> folder with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> useOutsideClick = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [isVisible, setIsVisible] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> ref = useRef();

  <span class="hljs-keyword">const</span> handleOutsideClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (ref.current) {
      setIsVisible(<span class="hljs-literal">false</span>);
    }
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'click'</span>, handleOutsideClick);
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">'click'</span>, handleOutsideClick);
    };
  }, []);

  <span class="hljs-keyword">return</span> [ref, isVisible, setIsVisible];
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useOutsideClick;
</code></pre>
<p>Here, we have created a custom hook that will show/hide the suggestion box.</p>
<p>Initially, we have declared a state to hide the suggestion box by setting the value to <code>false</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [isVisible, setIsVisible] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Then we have declared a ref:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ref = useRef();
</code></pre>
<p>We're returning this <code>ref</code> from our custom hook along with the <code>isVisible</code> and <code>setIsVisible</code> like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> [ref, isVisible, setIsVisible];
</code></pre>
<p>So inside the component wherever we're using the <code>useOutsideClick</code> hook, we can use this ref to assign it to the suggestion box. So if there are multiple input fields, then each input field will have its own suggestion box and hiding and showing functionality.</p>
<p>Inside the <code>handleOutsideClick</code> function, we have the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleOutsideClick = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">if</span> (ref.current) {
    setIsVisible(<span class="hljs-literal">false</span>);
  }
};
</code></pre>
<p>Here, we're checking for <code>ref.current</code> because we want to call the <code>setIsVisible</code> function only if the ref for the suggestion box is available and not every time we click on the page.</p>
<p>Then we have added event handlers to call the <code>handleOutsideClick</code> function:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'click'</span>, handleOutsideClick);
  <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">'click'</span>, handleOutsideClick);
  };
}, []);
</code></pre>
<p>We're also removing the event handler by returning a function from the <code>useEffect</code> hook once the component is unmounted.</p>
<h2 id="heading-how-to-create-a-reusable-react-component">How to Create a Reusable React Component</h2>
<p>Now, create an <code>InputControl.js</code> file inside the <code>components</code> folder with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">/* eslint-disable react-hooks/exhaustive-deps */</span>
<span class="hljs-keyword">import</span> React, { useState, useEffect, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">'lodash'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> AutoComplete <span class="hljs-keyword">from</span> <span class="hljs-string">'./AutoComplete'</span>;
<span class="hljs-keyword">import</span> useOutsideClick <span class="hljs-keyword">from</span> <span class="hljs-string">'../custom-hooks/useOutsideClick'</span>;

<span class="hljs-keyword">const</span> InputControl = <span class="hljs-function">(<span class="hljs-params">{ name, label, placeholder }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [documentRef, isVisible, setIsVisible] = useOutsideClick();
  <span class="hljs-keyword">const</span> [suggestions, setSuggestions] = useState([]);
  <span class="hljs-keyword">const</span> [selectedCountry, setSelectedCountry] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [searchTerm, setSearchTerm] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [errorMsg, setErrorMsg] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> ref = useRef();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    ref.current = _.debounce(processRequest, <span class="hljs-number">300</span>);
  }, []);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequest</span>(<span class="hljs-params">searchValue</span>) </span>{
    axios
      .get(<span class="hljs-string">'/countries.json'</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> countries = response.data;
        <span class="hljs-keyword">const</span> result = countries.filter(<span class="hljs-function">(<span class="hljs-params">country</span>) =&gt;</span>
          country.toLowerCase().includes(searchValue.toLowerCase())
        );
        setSuggestions(result);
        <span class="hljs-keyword">if</span> (result.length &gt; <span class="hljs-number">0</span>) {
          setIsVisible(<span class="hljs-literal">true</span>);
        } <span class="hljs-keyword">else</span> {
          setIsVisible(<span class="hljs-literal">false</span>);
        }
        setErrorMsg(<span class="hljs-string">''</span>);
      })
      .catch(<span class="hljs-function">() =&gt;</span> setErrorMsg(<span class="hljs-string">'Something went wrong. Try again later'</span>));
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSearch</span>(<span class="hljs-params">event</span>) </span>{
    event.preventDefault();
    <span class="hljs-keyword">const</span> { value } = event.target;
    setSearchTerm(value);
    ref.current(value);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSuggestionClick</span>(<span class="hljs-params">countryValue</span>) </span>{
    setSelectedCountry(countryValue);
    setIsVisible(<span class="hljs-literal">false</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"searchTerm"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>{label}<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"input-control"</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{searchTerm}</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleSearch}</span>
        <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"off"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{documentRef}</span>&gt;</span>
        {isVisible &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">AutoComplete</span>
            <span class="hljs-attr">isVisible</span>=<span class="hljs-string">{isVisible}</span>
            <span class="hljs-attr">suggestions</span>=<span class="hljs-string">{suggestions}</span>
            <span class="hljs-attr">handleSuggestionClick</span>=<span class="hljs-string">{handleSuggestionClick}</span>
          /&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {selectedCountry &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"selected-country"</span>&gt;</span>
          Your selected country: {selectedCountry}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}
      {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> InputControl;
</code></pre>
<p>In this file, we've created a reusable component with search and suggestions available in the component.</p>
<p>Initially, we're referencing the <code>useOutsideClick</code> hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [documentRef, isVisible, setIsVisible] = useOutsideClick();
</code></pre>
<p>We're storing the ref returned from the hook in the <code>documentRef</code> variable.<br>Whenever a user types something in the textbox, we're making an API call to get a list of countries with matching search criteria.</p>
<p>But to avoid the unnecessary API calls on every character entered in the textbox, we'll use the debounce method of the <a target="_blank" href="https://lodash.com/">lodash</a> library. It lets us call the API only after 300 milliseconds has passed once the user has stopped typing using the following code:</p>
<pre><code class="lang-js">ref.current = _.debounce(processRequest, <span class="hljs-number">300</span>);
</code></pre>
<p>The <code>_.debounce</code> function call returns a function that we have stored in the <code>ref.current</code> variable. We will call the function stored there once 300 milliseconds have passed.</p>
<p>We are using ref instead of a normal variable because we need this initialization to happen only once when the component is mounted. The value of the normal variable will get lost on every re-render of the component when some state or prop changes.</p>
<p>We are calling the function stored in <code>ref.current</code> from the <code>handleSearch</code> function by passing the user-entered value.</p>
<p>So once we call the function stored in <code>ref.current</code>, the <code>processRequest</code> function will be called behind the scenes.</p>
<p>The <code>processRequest</code> function will automatically receive the value passed to the <code>ref.current</code> function.</p>
<p>Inside the <code>processRequest</code> function, we make an API call to get the list of countries.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequest</span>(<span class="hljs-params">searchValue</span>) </span>{
  axios
    .get(<span class="hljs-string">'/countries.json'</span>)
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> countries = response.data;
      <span class="hljs-keyword">const</span> result = countries.filter(<span class="hljs-function">(<span class="hljs-params">country</span>) =&gt;</span>
        country.toLowerCase().includes(searchValue.toLowerCase())
      );
      setSuggestions(result);
      <span class="hljs-keyword">if</span> (result.length &gt; <span class="hljs-number">0</span>) {
        setIsVisible(<span class="hljs-literal">true</span>);
      } <span class="hljs-keyword">else</span> {
        setIsVisible(<span class="hljs-literal">false</span>);
      }
      setErrorMsg(<span class="hljs-string">''</span>);
    })
    .catch(<span class="hljs-function">() =&gt;</span> setErrorMsg(<span class="hljs-string">'Something went wrong. Try again later'</span>));
}
</code></pre>
<p>Here, once we have the response from the API, we're using the array filter method to filter out only the countries that match the provides search term.</p>
<p>Then we're setting out the list of countries in the suggestions state using <code>setSuggestions(result)</code>.</p>
<p>Next, we're checking the length of the result array to display or hide the suggestion box.</p>
<p>If you check the JSX that's returned from the component, it looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form.Group</span> <span class="hljs-attr">controlId</span>=<span class="hljs-string">"searchTerm"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Form.Label</span>&gt;</span>{label}<span class="hljs-tag">&lt;/<span class="hljs-name">Form.Label</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Form.Control</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">"input-control"</span>
      <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{searchTerm}</span>
      <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span>
      <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleSearch}</span>
      <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"off"</span>
      <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{documentRef}</span>&gt;</span>
      {isVisible &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">AutoComplete</span>
          <span class="hljs-attr">isVisible</span>=<span class="hljs-string">{isVisible}</span>
          <span class="hljs-attr">suggestions</span>=<span class="hljs-string">{suggestions}</span>
          <span class="hljs-attr">handleSuggestionClick</span>=<span class="hljs-string">{handleSuggestionClick}</span>
        /&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    {selectedCountry &amp;&amp; (
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"selected-country"</span>&gt;</span>
        Your selected country: {selectedCountry}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    )}
    {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
  <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Group</span>&gt;</span></span>
);
</code></pre>
<p>Here, for the input textbox we've added a <code>handleSearch</code> onChange handler which looks like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSearch</span>(<span class="hljs-params">event</span>) </span>{
  event.preventDefault();
  <span class="hljs-keyword">const</span> { value } = event.target;
  setSearchTerm(value);
  ref.current(value);
}
</code></pre>
<p>We update the <code>searchTerm</code> state with the value typed by the user. Then we're calling the function stored in the <code>ref.current</code> by passing it the value the user enters.</p>
<p>Calling <code>ref.current</code> internally calls the <code>processRequest</code> function where we're actually calling the API.</p>
<p>Then after the Input textbox, we've added a div with the ref to show the suggestions:</p>
<pre><code class="lang-js">&lt;div ref={documentRef}&gt;
  {isVisible &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AutoComplete</span>
      <span class="hljs-attr">isVisible</span>=<span class="hljs-string">{isVisible}</span>
      <span class="hljs-attr">suggestions</span>=<span class="hljs-string">{suggestions}</span>
      <span class="hljs-attr">handleSuggestionClick</span>=<span class="hljs-string">{handleSuggestionClick}</span>
    /&gt;</span></span>
  )}
&lt;/div&gt;
</code></pre>
<p>We're showing suggestions only if <code>isVisible</code> is true which happens when we get results from the API inside the <code>processRequest</code> function.</p>
<p>Here, we're passing the suggestions to display in the <code>AutoComplete</code> component.<br>Once we click on any of the suggestion, the <code>handleSuggestionClick</code> function gets executed which is updating the <code>selectedCountry</code> and hiding the suggestions:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSuggestionClick</span>(<span class="hljs-params">countryValue</span>) </span>{
  setSelectedCountry(countryValue);
  setIsVisible(<span class="hljs-literal">false</span>);
}
</code></pre>
<h2 id="heading-how-to-use-the-reusable-component">How to Use the Reusable Component</h2>
<p>Now, open the <code>App.js</code> file and add the following code inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> InputControl <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/InputControl'</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">"main"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React AutoSuggestion Demo<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">"search-form"</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">InputControl</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"country"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Enter Country"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type a country name"</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>&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, start the application by running the following command from the terminal or command prompt:</p>
<pre><code class="lang-js">yarn start
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, once you select any value from the suggestion, the selected value gets displayed below the textbox.</p>
<p><strong>Note:</strong> we have created a separate <code>InputControl</code> component that displays the input field along with its suggestion box.</p>
<p>So we can reuse the same <code>InputControl</code> component again to display suggestions in another input textbox as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Form } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap'</span>;
<span class="hljs-keyword">import</span> InputControl <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/InputControl'</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">"main"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React AutoSuggestion Demo<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">"search-form"</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">InputControl</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"country"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Enter Country"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type a country name"</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">InputControl</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"country"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">"Enter Country"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type a country name"</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>&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><img src="https://www.freecodecamp.org/news/content/images/2021/08/3.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we've added another <code>InputControl</code> component for the country so we're able to handle the suggestion for each input textbox separately.</p>
<p>So if you want to display different suggestions for another text box, you can just pass an extra prop to the <code>InputControl</code> component and based on that prop show different results in suggestion box.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As we have seen in this tutorial, by creating a reusable <code>InputControl</code> component and using <code>ref</code> to manage each input textbox's suggestion separately, we're able to create a truly reusable component for showing autocomplete suggestions.</p>
<p><strong>You can find the complete source code for this tutorial in <a target="_blank" href="https://github.com/myogeshchavan97/react-autosuggestion-app">this repository</a> and live demo <a target="_blank" href="https://react-autosuggestion-app.netlify.app/">here</a>.</strong></p>
<h2 id="heading-thanks-for-reading"><strong>Thanks for reading!</strong></h2>
<p>If you want to learn Redux in detail from scratch and build 3 apps along with the <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">complete food ordering app</a>, check out the <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls</li>
<li>Build 3 different apps using Redux</li>
</ul>
<p>and much more.</p>
<p>Finally, we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=2zaPDfCKAvM">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Redux for Beginners – Learn Redux Basics with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ Redux can be confusing for beginner React developers to understand. There are a lot of concepts you need to know to use it properly, like reducers, actions, store, pure functions, immutability, and much more. But every React developer should know the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/redux-for-beginners/</link>
                <guid isPermaLink="false">66bc552fd94fa6cb67b84504</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Tue, 18 May 2021 16:18:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/pexels-philipp-birmes-830891.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Redux can be confusing for beginner React developers to understand. There are a lot of concepts you need to know to use it properly, like reducers, actions, store, pure functions, immutability, and much more.</p>
<p>But every React developer should know the basics of how to work with Redux, since industry projects often use Redux to manage larger projects.</p>
<p>So in this article, we'll explore the basics of Redux and how to use it.</p>
<p>Here's a preview of the app which we'll be building in this article. It's a great project you can add to your portfolio and resume.</p>
<div class="embed-wrapper"><iframe width="800" height="500" src="https://www.youtube.com/embed/izSw74H08Bc?mute=1" title="Embedded content" loading="lazy"></iframe></div>

<h2 id="heading-what-is-redux">What Is Redux?</h2>
<p>Redux is a state management library that helps you better manage state in your applications.</p>
<p>The Redux library is not specific to React. It's a library that you can use in any other library or framework like Angular, Vue, and even vanilla JavaScript.</p>
<p>But developers mostly use Redux when working with React.</p>
<p>Redux provides a single store that you can use to manage a large amount of data.</p>
<h2 id="heading-how-to-get-started-with-redux">How to Get Started with Redux</h2>
<p>Let's create a new React project so we can learn Redux basics.</p>
<p>Execute the following command in the terminal/command prompt to create a new React project using create-react-app:</p>
<pre><code class="lang-js">npx create-react-app redux-demo
</code></pre>
<blockquote>
<p><code>npx</code> in this case allows us to use the <code>create-react-app</code> npm package to create a new React project without installing it on our local machine.</p>
</blockquote>
<p>Once you've created the project, delete all the files from the <code>src</code> folder and create a new file <code>index.js</code> inside the <code>src</code> folder.</p>
<p>Now open the terminal again and execute the following command from the <code>redux-demo</code> folder:</p>
<pre><code class="lang-js">npm install redux@<span class="hljs-number">4.1</span><span class="hljs-number">.0</span>
</code></pre>
<p>The above command will install the Redux library with version <code>4.1.0</code> to use in your project (which is the latest version at the time of writing this article).</p>
<h2 id="heading-how-to-create-the-redux-store">How to Create the Redux Store</h2>
<p>In Redux, you use the store to manage and track the data that's changing in the application.</p>
<p>To create a store, we need to import the <code>createStore</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
</code></pre>
<p>The <code>createStore</code> function accepts three arguments:</p>
<ul>
<li>the first argument is a function that is normally known as a reducer (required)</li>
<li>the second argument is the initial value of the state (optional)</li>
<li>the third argument is an enhancer where we can pass middleware, if any (optional)</li>
</ul>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'reducer called'</span>);
  <span class="hljs-keyword">return</span> state;
};

<span class="hljs-keyword">const</span> store = createStore(reducer, <span class="hljs-number">0</span>);
</code></pre>
<p>Here, we've first defined a reducer function using ES6 arrow function syntax. You can use the normal function instead of the arrow function if you want.</p>
<p>Inside the reducer function, we're logging some text to the console and then returning the value of the state from the function.</p>
<p>Then we pass that reducer function to the <code>createStore</code> function as the first argument and <code>0</code> as the initial value of the state as the second argument.</p>
<p>The <code>createStore</code> function returns a store that we can use to manage the application data.</p>
<p>The reducer function receives state and action as the parameters.</p>
<p>The initial value of the state which we passed as <code>0</code> for the <code>createStore</code> function is automatically passed as the value of the <code>state</code> parameter.</p>
<p>But it's a much more common practice to initialize the state inside the reducer itself rather than passing it as a second argument to the <code>createStore</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'reducer called'</span>);
  <span class="hljs-keyword">return</span> state;
};

<span class="hljs-keyword">const</span> store = createStore(reducer);
</code></pre>
<p>Here, we're using ES6 default parameter syntax for initializing the state parameter to value <code>0</code>.</p>
<p>Once the store is created, we can use the <code>subscribe</code> method provided by the store to subscribe to the changes in the store as shown below:</p>
<pre><code class="lang-js">store.subscribe(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'current state'</span>, store.getState());
});
</code></pre>
<p>Here, using the <code>subscribe</code> function, we're registering a callback function that will be called once the store is changed.</p>
<p>And inside the callback function, we're calling the <code>store.getState</code> method to get the current value of the state.</p>
<p>Now, open the <code>src/index.js</code> file and add the following contents inside it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'reducer called'</span>);
  <span class="hljs-keyword">return</span> state;
};

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

store.subscribe(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'current state'</span>, store.getState());
});
</code></pre>
<p>Now, if you run the application by executing the <code>npm start</code> command from the terminal and access <a target="_blank" href="http://localhost:3000/">http://localhost:3000/</a>, you will see the <code>reducer called</code> message printed in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/reducer_log.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is because the reducer gets called immediately once we pass it to the <code>createStore</code> function.</p>
<h2 id="heading-how-to-change-the-store">How to Change the Store</h2>
<p>Now we're done with creating the store. But the store is not much use to us right now. This is because the store is connected using the reducer function, but we have not added any code inside the reducer to manage the store. So let's do that.</p>
<p><strong>The only way to change the store is by dispatching actions.</strong></p>
<p>An action is an object sent to the store like this:</p>
<pre><code class="lang-js">store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span>
})
</code></pre>
<p>Here, we're calling the dispatch function available on the <code>store</code> to send an action with the type <code>INCREMENT</code> to the store.</p>
<p>The dispatch function takes an object as a parameter which is known as an action.</p>
<p>The action must have a <code>type</code> property as shown above. If you don't pass the <code>type</code> property then you will get an error.</p>
<blockquote>
<p>It's a common practice and recommended to specify the <code>type</code> value in uppercase.</p>
</blockquote>
<p>The type can be any operation you want to perform, like <code>ADD_USER</code>, <code>DELETE_RECORD</code>, <code>GET_USERS</code> and so on.</p>
<p>If you have multiple words, you can separate them with underscores like this <code>{ type: 'INCREMENT_NUMBER' }</code>.</p>
<p>Now, open the <code>index.js</code> file and replace its contents with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

<span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'INCREMENT'</span>) {
    <span class="hljs-keyword">return</span> state + <span class="hljs-number">1</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'DECREMENT'</span>) {
    <span class="hljs-keyword">return</span> state - <span class="hljs-number">1</span>;
  }

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

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

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

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

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

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span>
});
</code></pre>
<p>Now, if you run the application by executing the <code>npm start</code> command from the terminal, you will see the following logs printed in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/changing_store-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, for every action dispatched to the store, the store gets changed. So we're able to see the different values of the state in the console.</p>
<p>In the above code, our reducer function looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'INCREMENT'</span>) {
    <span class="hljs-keyword">return</span> state + <span class="hljs-number">1</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'DECREMENT'</span>) {
    <span class="hljs-keyword">return</span> state - <span class="hljs-number">1</span>;
  }

  <span class="hljs-keyword">return</span> state;
};
</code></pre>
<p>Whenever we call the <code>store.dispatch</code> function, the reducer function will be called. Whatever is returned from the reducer will become the new value of the store.</p>
<p>So the first time we dispatch an action to the store like this:</p>
<pre><code class="lang-js">store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span>
});
</code></pre>
<p>the first if condition inside the reducer function will be executed. It will increment the <code>state</code> value to <code>1</code> which was initially initialized to <code>0</code> using ES6 default parameter syntax. Then it will be returned from the reducer function.</p>
<p><strong>Note that we're using the value of the <code>state</code> to calculate the new value and we're not modifying the original <code>state</code> value like this:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (action.type === <span class="hljs-string">'INCREMENT'</span>) {
   state = state + <span class="hljs-number">1</span>;
   <span class="hljs-keyword">return</span> state;
}
</code></pre>
<p>So the above code is not correct, because in the reducer we should not modify the original state. Doing so will create issues in your application and so it's not recommended.</p>
<p>And because we've added the <code>store.subscribe</code> function in the <code>index.js</code> file, we get notified about the changing store as we can see the logs in the console.</p>
<p>So when we again call the dispatch with type <code>INCREMENT</code>, the first if condition will be executed again. So it'll add 1 to the previous state value which was 1, and the final state value will become 2.</p>
<p>Then we're dispatching the <code>DECREMENT</code> action to the store like this:</p>
<pre><code class="lang-js">store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span>
});
</code></pre>
<p>which will execute the else condition inside the reducer and it will decrement the state value by 1 (so 2 - 1  will become 1).</p>
<p>Note that, inside the reducer, we're also returning state at the end. So if none of the condition matches, the default previous state will be returned from the function.</p>
<p>It's a common practice to use a switch statement inside the reducer instead of the if-else condition like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> state + <span class="hljs-number">1</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> state - <span class="hljs-number">1</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>In addition to the type, we can also pass extra information as a part of the action.</p>
<p>Replace the contents of the <code>index.js</code> file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;

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

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

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

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

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

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">2</span>
});
</code></pre>
<p>Now, if you run the application by executing the <code>npm start</code> command from the terminal, you will see the following logs printed in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/with_payload-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, while dispatching an action to the store, we're passing a <code>payload</code> with some value which we're using inside the reducer to increment or decrement the store value.</p>
<p>Here, we've used <code>payload</code> as a property name but you can name it whatever you want.</p>
<p>Our reducer function looks like this now:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">state = <span class="hljs-number">0</span>, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'INCREMENT'</span>:
      <span class="hljs-keyword">return</span> state + action.payload;
    <span class="hljs-keyword">case</span> <span class="hljs-string">'DECREMENT'</span>:
      <span class="hljs-keyword">return</span> state - action.payload;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};
</code></pre>
<p>So when we dispatch actions with type <code>INCREMENT</code> like this:</p>
<pre><code class="lang-js">store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">1</span>
});

store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'INCREMENT'</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">5</span>
});
</code></pre>
<p>the following code from the reducer will be executed:</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> state + action.payload;
</code></pre>
<p>This will first add 1 and then 5 to the previous value of the state, so we go from 1 to 6. And because of the <code>DECREMENT</code> action type:</p>
<pre><code class="lang-js">store.dispatch({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'DECREMENT'</span>,
  <span class="hljs-attr">payload</span>: <span class="hljs-number">2</span>
});
</code></pre>
<p>we go from 6 to 4. So the final value of the store will become 4.</p>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/goofy-hooks-y1w9s?file=/src/index.js">Code Sandbox Demo</a>.</p>
<h2 id="heading-thanks-for-reading">Thanks for reading!</h2>
<p>This was a quick introduction to Redux from my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course. If you want to learn Redux in detail and build a complete food ordering app, you can check it out.</p>
<p>In the course, you will learn:</p>
<ul>
<li>Basic and advanced Redux</li>
<li>How to manage the complex state of array and objects</li>
<li>How to use multiple reducers to manage complex redux state</li>
<li>How to debug a Redux application</li>
<li>How to use Redux in React using the react-redux library to make your app reactive.</li>
<li>How to use the redux-thunk library to handle async API calls </li>
</ul>
<p>and much more.</p>
<p>Finally we'll build a complete <a target="_blank" href="https://www.youtube.com/watch?v=izSw74H08Bc">food ordering app</a> from scratch with stripe integration for accepting payments and deploy it to production.</p>
<p>You can get the course for just $12 instead of the original price of $19 along with the free copy of my popular <a target="_blank" href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a> book if you purchase by 19th May, 2021.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Tutorial – How to Work with Multiple Checkboxes ]]>
                </title>
                <description>
                    <![CDATA[ Handling multiple checkboxes in React is completely different from how you use regular HTML checkboxes. So in this article, we'll see how to work with multiple checkboxes in React. You will learn: How to use a checkbox as a Controlled Input in React... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-work-with-multiple-checkboxes-in-react/</link>
                <guid isPermaLink="false">66bc551ca30f8b3984dad869</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Thu, 13 May 2021 18:17:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/checkbox_selection.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Handling multiple checkboxes in React is completely different from how you use regular HTML checkboxes.</p>
<p>So in this article, we'll see how to work with multiple checkboxes in React.</p>
<p>You will learn:</p>
<ul>
<li>How to use a checkbox as a Controlled Input in React</li>
<li>How to use the array map and reduce methods for complex calculation</li>
<li>How to create an array of a specific length pre-filled with some specific value</li>
</ul>
<p>and much more.</p>
<p>This article is a part of my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course. Here's a <a target="_blank" href="https://www.youtube.com/watch?v=izSw74H08Bc">preview of the app</a> we'll be building in the course.</p>
<p>So let's get started.</p>
<h2 id="heading-how-to-work-with-single-checkbox">How to Work with Single Checkbox</h2>
<p>Let's start with single checkbox functionality before moving on to multiple checkboxes.</p>
<p>In this article, I will be using React Hooks syntax for creating components. So if you're not familiar with React Hooks, check out my <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?source=friends_link&amp;sk=89baff89ec8bc637e7c13b7554904e54">Introduction to React Hooks</a> article.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js">&lt;div className=<span class="hljs-string">"App"</span>&gt;
  Select your pizza topping:
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"topping"</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">id</span>=<span class="hljs-string">"topping"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"topping"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Paneer"</span> /&gt;</span>Paneer
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>Here's a <a target="_blank" href="https://codesandbox.io/s/young-snow-lzplh?file=/src/App.js">Code Sandbox Demo</a>.</p>
<p>In the above code, we've just declared a single checkbox which is similar to how we declare an HTML checkbox.</p>
<p>So we're able to easily check and uncheck the checkbox as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/check_uncheck-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>But to display on the screen whether it's checked or not, we need to convert it to Controlled Input.</p>
<p>In React, Controlled Input is managed by state, so the input value can be changed only by changing the state related to that input.</p>
<p>Take a look at the below code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [isChecked, setIsChecked] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> handleOnChange = <span class="hljs-function">() =&gt;</span> {
    setIsChecked(!isChecked);
  };

  <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>
      Select your pizza topping:
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"topping"</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">id</span>=<span class="hljs-string">"topping"</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"topping"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">"Paneer"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{isChecked}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleOnChange}</span>
        /&gt;</span>
        Paneer
      <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">"result"</span>&gt;</span>
        Above checkbox is {isChecked ? "checked" : "un-checked"}.
      <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>Here's a <a target="_blank" href="https://codesandbox.io/s/dazzling-oskar-qcil8?file=/src/App.js">Code Sandbox Demo</a>.</p>
<p>In the above code, we've declared the <code>isChecked</code> state in the component with the initial value of <code>false</code> using the <code>useState</code> hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [isChecked, setIsChecked] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Then for the input checkbox, we've given two extra props <code>checked</code> and <code>onChange</code> like this:</p>
<pre><code class="lang-js">&lt;input
  ...
  checked={isChecked}
  onChange={handleOnChange}
/&gt;
</code></pre>
<p>Whenever we click on the checkbox the <code>handleOnChange</code> handler function will be called which we use to set the value of <code>isChecked</code> state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleOnChange = <span class="hljs-function">() =&gt;</span> {
  setIsChecked(!isChecked);
};
</code></pre>
<p>So if the checkbox is checked, we're setting the <code>isChecked</code> value to <code>false</code>. But if the checkbox is unchecked, we're setting the value to <code>true</code> using <code>!isChecked</code>. Then we pass that value in the input checkbox for the prop <code>checked</code>.</p>
<p>This way the input checkbox becomes a controlled input whose value is managed by the state.</p>
<p>Note that in React, it's always recommended to use Controlled Input for input fields even if the code looks complicated. This guarantees that the input change happens inside only the <code>onChange</code> handler.</p>
<p>The state of the input will not be changed in any other way and you'll always get the correct and updated value of the state of the input.</p>
<p>Only in rare cases, you can use React ref to use the input in an uncontrolled way.</p>
<h2 id="heading-how-to-handle-multiple-checkboxes">How to Handle Multiple Checkboxes</h2>
<p>Now, let's look at how you'll handle multiple checkboxes.</p>
<p>Take a look at <a target="_blank" href="https://codesandbox.io/s/mystifying-tu-xlpgb?file=/src/App.js">this Code Sandbox Demo</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/multiple_checkboxes-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, we're displaying a list of toppings and their corresponding price. Based on which toppings are selected, we need to display the total amount.</p>
<p>Previously, with the single checkbox, we only had the <code>isChecked</code> state and we changed the state of the checkbox based on that.</p>
<p>But now we have a lot of checkboxes, so it's not practical to add multiple <code>useState</code> calls for each checkbox.</p>
<p>So let's declare an array in the state indicating the state of each checkbox.</p>
<p>To create an array equal to the length of the number of checkboxes, we can use the array <code>fill</code> method like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [checkedState, setCheckedState] = useState(
    <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(toppings.length).fill(<span class="hljs-literal">false</span>)
);
</code></pre>
<p>Here, we've declared a state with an initial value as an array filled with the value <code>false</code>.</p>
<p>So if we have 5 toppings then the <code>checkedState</code> state array will contain 5 <code>false</code> values like this:</p>
<pre><code class="lang-js">[<span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>]
</code></pre>
<p>And once we check/uncheck the checkbox, we'll change the corresponding <code>false</code> to <code>true</code> and <code>true</code> to <code>false</code>.</p>
<p>Here's a final <a target="_blank" href="https://codesandbox.io/s/wild-silence-b8k2j?file=/src/App.js">Code Sandbox Demo</a>.</p>
<p>The complete <code>App.js</code> code looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { toppings } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils/toppings"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./styles.css"</span>;

<span class="hljs-keyword">const</span> getFormattedPrice = <span class="hljs-function">(<span class="hljs-params">price</span>) =&gt;</span> <span class="hljs-string">`$<span class="hljs-subst">${price.toFixed(<span class="hljs-number">2</span>)}</span>`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [checkedState, setCheckedState] = useState(
    <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(toppings.length).fill(<span class="hljs-literal">false</span>)
  );

  <span class="hljs-keyword">const</span> [total, setTotal] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> handleOnChange = <span class="hljs-function">(<span class="hljs-params">position</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> updatedCheckedState = checkedState.map(<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</span>
      index === position ? !item : item
    );

    setCheckedState(updatedCheckedState);

    <span class="hljs-keyword">const</span> totalPrice = updatedCheckedState.reduce(
      <span class="hljs-function">(<span class="hljs-params">sum, currentState, index</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (currentState === <span class="hljs-literal">true</span>) {
          <span class="hljs-keyword">return</span> sum + toppings[index].price;
        }
        <span class="hljs-keyword">return</span> sum;
      },
      <span class="hljs-number">0</span>
    );

    setTotal(totalPrice);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Select Toppings<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"toppings-list"</span>&gt;</span>
        {toppings.map(({ name, price }, index) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"toppings-list-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">"left-section"</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">id</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">custom-checkbox-</span>${<span class="hljs-attr">index</span>}`}
                    <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span>
                    <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
                    <span class="hljs-attr">checked</span>=<span class="hljs-string">{checkedState[index]}</span>
                    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{()</span> =&gt;</span> handleOnChange(index)}
                  /&gt;
                  <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">custom-checkbox-</span>${<span class="hljs-attr">index</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">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">"right-section"</span>&gt;</span>{getFormattedPrice(price)}<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">li</span>&gt;</span>
          );
        })}
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"toppings-list-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">"left-section"</span>&gt;</span>Total:<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">"right-section"</span>&gt;</span>{getFormattedPrice(total)}<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">li</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Let's understand what we're doing here.</p>
<p>We've declared the input checkbox as shown below:</p>
<pre><code class="lang-js">&lt;input
  type=<span class="hljs-string">"checkbox"</span>
  id={<span class="hljs-string">`custom-checkbox-<span class="hljs-subst">${index}</span>`</span>}
  name={name}
  value={name}
  checked={checkedState[index]}
  onChange={<span class="hljs-function">() =&gt;</span> handleOnChange(index)}
/&gt;
</code></pre>
<p>Here, we've added a <code>checked</code> attribute with the corresponding value of <code>true</code> or <code>false</code> from the <code>checkedState</code> state. So each checkbox will have the correct value of its checked state.</p>
<p>We've also added an <code>onChange</code> handler and we're passing the <code>index</code> of the checkbox which is checked/un-checked to the <code>handleOnChange</code> method.</p>
<p>The <code>handleOnChange</code> handler method looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleOnChange = <span class="hljs-function">(<span class="hljs-params">position</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> updatedCheckedState = checkedState.map(<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</span>
    index === position ? !item : item
  );

  setCheckedState(updatedCheckedState);

  <span class="hljs-keyword">const</span> totalPrice = updatedCheckedState.reduce(
    <span class="hljs-function">(<span class="hljs-params">sum, currentState, index</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (currentState === <span class="hljs-literal">true</span>) {
        <span class="hljs-keyword">return</span> sum + toppings[index].price;
      }
      <span class="hljs-keyword">return</span> sum;
    },
    <span class="hljs-number">0</span>
  );

  setTotal(totalPrice);
};
</code></pre>
<p>Here, we're first looping over the <code>checkedState</code> array using the array <code>map</code> method. If the value of the passed <code>position</code> parameter matches with the current <code>index</code>, then we reverse its value. Then, if the value is <code>true</code> it will be converted to <code>false</code> using <code>!item</code> and if the value is <code>false</code>, then it will be converted to <code>true</code>.</p>
<p>If the <code>index</code> does not match with the provided <code>position</code> parameter, then we're not reversing its value but we're just returning the value as it is.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> updatedCheckedState = checkedState.map(<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</span>
  index === position ? !item : item
);

<span class="hljs-comment">// the above code is the same as the below code</span>

<span class="hljs-keyword">const</span> updatedCheckedState = checkedState.map(<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (index === position) {
    <span class="hljs-keyword">return</span> !item;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> item;
  }
});
</code></pre>
<p>I used the ternary operator <code>?:</code> because it makes the code shorter but you can use any array method.</p>
<p>If you're not familiar with how array methods like <code>map</code> or <code>reduce</code> work, then check out <a target="_blank" href="https://www.freecodecamp.org/news/complete-introduction-to-the-most-useful-javascript-array-methods/">this article</a> I wrote.</p>
<p>Next, we're setting the <code>checkedState</code> array to the <code>updatedCheckedState</code> array. This is important because if you don't update the <code>checkedState</code> state inside the <code>handleOnChange</code> handler, then you will not be able to check/uncheck the checkbox.</p>
<p>This is because we're using the <code>checkedState</code> value for the checkbox to determine if the checkbox is checked or not (as it's a controlled input as shown below):</p>
<pre><code class="lang-js">&lt;input
  type=<span class="hljs-string">"checkbox"</span>
  ...
  checked={checkedState[index]}
  onChange={<span class="hljs-function">() =&gt;</span> handleOnChange(index)}
/&gt;
</code></pre>
<p>Note that we've created a separate <code>updatedCheckedState</code> variable and we're passing that variable to the <code>setCheckedState</code> function. We're using the <code>reduce</code> method on <code>updatedCheckedState</code> and not on the original <code>checkedState</code> array.</p>
<p>This is because, by default, the <code>setCheckedState</code> function used to update the state is asynchronous.</p>
<p>Just because you called the <code>setCheckedState</code> function does not guarantee that you will get the updated value of the <code>checkedState</code> array in the next line.</p>
<p>So we've created a separate variable and used that in the <code>reduce</code> method.</p>
<p>You can read <a target="_blank" href="https://www.freecodecamp.org/news/what-is-state-in-react-explained-with-examples/">this article</a> if you're not familiar with how state works in React.</p>
<p>Then to calculate the total price, we're using the array <code>reduce</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> totalPrice = updatedCheckedState.reduce(
  <span class="hljs-function">(<span class="hljs-params">sum, currentState, index</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (currentState === <span class="hljs-literal">true</span>) {
      <span class="hljs-keyword">return</span> sum + toppings[index].price;
    }
    <span class="hljs-keyword">return</span> sum;
  },
  <span class="hljs-number">0</span>
);
</code></pre>
<p>The array <code>reduce</code> method receives four parameters, of which we're using only three: <code>sum</code>, <code>currentState</code> and <code>index</code>. You can use different names if you want as they're just parameters.</p>
<p>We're also passing <code>0</code> as the initial value, which is also known as the <code>accumulator</code> value for the <code>sum</code> parameter.</p>
<p>Then inside the reduce function, we're checking if the current value of the <code>checkedState</code> array is <code>true</code> or not.</p>
<p>If it's <code>true</code>, that means the checkbox is checked so we're adding the value of the corresponding <code>price</code> using <code>sum + toppings[index].price</code>.</p>
<p>If the <code>checkedState</code> array value is <code>false</code>, then we're not adding its price but just returning the calculated previous value of <code>sum</code>.</p>
<p>Then we're setting that <code>totalPrice</code> value to the <code>total</code> state using <code>setTotal(totalPrice)</code></p>
<p>This way we're correctly able to calculate the total price for the selected toppings as you can see below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/toppings-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's a <a target="_blank" href="https://b8k2j.csb.app/">Preview link</a> of the above Code Sandbox demo to try for yourself.</p>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>Most developers struggle with understanding how Redux works. But every React developer should be aware of how to work with Redux, as industry projects mostly use Redux for managing larger projects.</p>
<p>So to make it easy for you, I have launched a <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
<p>In this course, you will learn Redux from the absolute beginning and you'll also build a complete <a target="_blank" href="https://www.youtube.com/watch?v=izSw74H08Bc">food ordering app</a> from scratch using Redux.</p>
<p>Click the below image to join the course and get the limited-time discount offer and also get my popular Mastering Modern JavaScript book for free.</p>
<p><a href="https://bit.ly/3w0DGum" target="_blank"><img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg" width="600" height="400" alt="banner" loading="lazy"></a></p>
<p><strong>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Common Mistakes React Developers Make – And How to Fix Them ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll see some of the common mistakes that React developers make, and how you can avoid them. So let's get started. Don't Forget that Every Route Change Mounts and Unmounts a Component Whenever you're using routing in a React applica... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/common-mistakes-react-developers-make-and-how-to-fix-them/</link>
                <guid isPermaLink="false">66bc54fecd8a65d579e3a9f5</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Mon, 03 May 2021 16:40:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/06/christin-hume-mfB1B1s4sMc-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll see some of the common mistakes that React developers make, and how you can avoid them.</p>
<p>So let's get started.</p>
<h2 id="heading-dont-forget-that-every-route-change-mounts-and-unmounts-a-component">Don't Forget that Every Route Change Mounts and Unmounts a Component</h2>
<p>Whenever you're using routing in a React application, you declare routes inside the <code>Switch</code> component. This means that only one component with the matching route is displayed at a time.</p>
<p>Therefore, whenever you go from one route to another, the previously displayed component is unmounted and the component with the new matching route is mounted.</p>
<p>If you need to persist some data across a route change, you need to declare it in the component which encapsulates the routes. It could be the <code>App</code> component in the following Code Sandbox, or some other way of persisting data like using <a target="_blank" href="https://javascript.plainenglish.io/everything-you-need-to-know-about-html5-local-storage-and-session-storage-479c63415c0a?source=friends_link&amp;sk=f429aa5008683a3b0359db43f976efb3">local storage or session storage</a></p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codesandbox.io/embed/hopeful-faraday-hqz9x?file=/src/App.js" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodeSandbox embed" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin" loading="lazy"></iframe></div>
<p>As you can see in the above Code Sandbox, whenever we change the route by clicking on the links, the corresponding <code>console.log</code> gets displayed on the console. This indicates that the previous component is unmounted and a new component is mounted.</p>
<h2 id="heading-dont-use-the-wrong-setstate-syntax">Don't Use the Wrong setState Syntax</h2>
<p>Whenever you declare some state inside a class-based component, it's always an object like this:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.state = {
 <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span>
}
</code></pre>
<p>So whenever you use the updater form of the setState syntax to update the state, it looks like this:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">counter</span>: prevState.counter + <span class="hljs-number">1</span>
  };
});
</code></pre>
<p>Since state is an object, <code>prevState</code> is also an object – so you access the <code>counter</code> using <code>prevState.counter</code>.</p>
<p>But when you're using functional components with React Hooks, the state can be an object or a non-object value as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [counter, setCounter] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Here, the value of <code>counter</code> is not an object but it's a number. So to update the state using updater syntax, you'll write the code like this:</p>
<pre><code class="lang-js">setCounter(<span class="hljs-function">(<span class="hljs-params">prevCounter</span>) =&gt;</span> prevCounter + <span class="hljs-number">1</span>);
</code></pre>
<p>Here, the <code>prevCounter</code> is a number. So you don't use <code>prevCounter.counter</code> – just <code>prevCounter</code>. Or you can simplify it as shown below:</p>
<pre><code class="lang-js">setCounter(<span class="hljs-function">(<span class="hljs-params">counter</span>) =&gt;</span> counter + <span class="hljs-number">1</span>);
</code></pre>
<blockquote>
<p>Check out <a target="_blank" href="https://www.freecodecamp.org/news/what-is-state-in-react-explained-with-examples/">my article here</a> for a complete introduction to React state.</p>
</blockquote>
<h2 id="heading-dont-call-hooks-from-class-components">Don't Call Hooks from Class Components</h2>
<p>Starting with version 16.8.0, React introduced Hooks. They allow you to write better React code and make use of state and component life cycle methods inside functional components.</p>
<blockquote>
<p>Check out <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?source=friends_link&amp;sk=89baff89ec8bc637e7c13b7554904e54">my article here</a> for an introduction to React hooks.</p>
</blockquote>
<p>To make coding easier, React provides many hooks like:</p>
<ul>
<li>The <code>useParams</code> hook to access URL parameters when using React Routing</li>
<li>The <code>useHistory</code> hook to get access to history API inside any component</li>
<li>The <code>useRef</code> hook to get access to the DOM element</li>
</ul>
<p>and many other hooks.</p>
<p>But all of these hooks (which usually start with the <code>use</code> keyword) work only inside functional components.</p>
<p>If you have a class-based component then you can't use these hooks. You need to refactor your code to convert it to functional components. If you don't, you might get an error like the one in the below screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/hook_error.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-dont-forget-to-add-a-key-prop-when-using-the-array-map-method">Don't Forget to Add a Key Prop When Using the Array <code>map</code> Method</h2>
<p>Take a look at <a target="_blank" href="https://codesandbox.io/s/quirky-shockley-bjd6z?file=/src/index.js">this Code Sandbox Demo</a>.</p>
<p>Here, to display a list of items, you can use the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Items = <span class="hljs-function">(<span class="hljs-params">{ items }</span>) =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ol</span>&gt;</span>
    {items.map((item) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">Item</span> <span class="hljs-attr">item</span>=<span class="hljs-string">{item}</span> /&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span></span>
);
</code></pre>
<p>In React, you'll usually use the array <code>map</code> method to display a list of items stored in an array.</p>
<p>But as soon as you add an item to the list in the above Code Sandbox, you will see a missing key warning displayed in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/missing-key.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is because every time you're using the array <code>map</code> method to loop over the items, you need to provide a unique <code>key</code> prop. React uses this to identify which elements on the screen need to be re-rendered, so adding the <code>key</code> prop helps you avoids unnecessary re-rendering in your app.</p>
<p>Here's an updated <a target="_blank" href="https://codesandbox.io/s/boring-greider-olko7?file=/src/index.js">Code Sandbox Demo</a> with the added <code>key</code> prop.</p>
<p>Here, I've provided a unique <code>key</code> prop to each element we're looping over like this:</p>
<pre><code class="lang-js">&lt;Item item={item} key={index} /&gt;
</code></pre>
<p>Now if you try to add some items, you won't get any warnings in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/added-key.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<blockquote>
<p>Note: In the above code, as the elements not re-ordered or removed, using <code>index</code> as <code>key</code> works fine. But if you're removing or changing the displayed elements' order, then you need to provide a unique key instead of using <code>index</code>.</p>
</blockquote>
<h2 id="heading-dont-use-inline-functions-the-wrong-way">Don't Use Inline Functions the Wrong Way</h2>
<p>Take a look at <a target="_blank" href="https://codesandbox.io/s/stupefied-breeze-66nyr?file=/src/index.js">this Code Sandbox Demo</a>.</p>
<p>Here, I've added some items to the state:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [items, setItems] = useState([<span class="hljs-string">"one"</span>, <span class="hljs-string">"two"</span>]);
</code></pre>
<p>and we're looping over them to display on the screen:</p>
<pre><code class="lang-jsx">{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">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
    {item} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleRemoveItem(item)}</span>&gt;</span>Remove<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
))}
</code></pre>
<p>If you check the application, you will see that no items are displayed on the screen. Adding new items also doesn't work as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/wrong_inline.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is because of the <code>onClick</code>  handler for the button:</p>
<pre><code class="lang-jsx">&lt;button onClick={handleRemoveItem(item)}&gt;Remove&lt;/button&gt;
</code></pre>
<p>Here, we're calling the <code>handleRemoveItem</code> method when the user clicks on the button – but the way we're calling the method is wrong.</p>
<p>So if you don't need to pass any parameters, you use the following syntax:</p>
<pre><code class="lang-jsx">&lt;button onClick={handleRemoveItem}&gt;Remove&lt;/button&gt;
</code></pre>
<p>But later if you decide to pass some parameter to the function, you need to call the handler inside the inline function like this:</p>
<pre><code class="lang-jsx">&lt;button onClick={<span class="hljs-function">() =&gt;</span> handleRemoveItem(item)}&gt;Remove&lt;/button&gt;
</code></pre>
<p>Most React developers forget to add an inline function and then it takes hours of debugging to understand why something does not work.</p>
<p>Here's an updated working <a target="_blank" href="https://codesandbox.io/s/polished-moon-02iug?file=/src/index.js">Code Sandbox Demo</a>.</p>
<h3 id="heading-thanks-for-reading"><strong>Thanks for reading!</strong></h3>
<p>Starting with ES6, there are many useful additions to JavaScript like:</p>
<ul>
<li>ES6 Destructuring</li>
<li>Import and Export Syntax</li>
<li>Arrow functions</li>
<li>Promises</li>
<li>Async/await</li>
<li>Optional chaining operator and a lot more.</li>
</ul>
<p><strong>You can learn everything about all the ES6+ features in detail in my <a target="_blank" href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a> book.</strong></p>
<blockquote>
<p>Check out free preview contents of the book <a target="_blank" href="https://www.freecodecamp.org/news/learn-modern-javascript/">here</a>.</p>
</blockquote>
<p>Also, you can check out my <strong>free</strong> <a target="_blank" href="https://yogeshchavan1.podia.com/react-router-introduction">Introduction to React Router</a> course to learn React Router from scratch.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
<p><a href="https://bit.ly/3w0DGum" target="_blank"><img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg" width="600" height="400" alt="banner" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a React Application with Load More Functionality using React Hooks ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will build a React application using class components. Then we'll convert it to functional components using React Hooks in a step-by-step way. By building this app, you will learn: How to make API calls How to implement load more... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-react-application-with-load-more-functionality-react-hooks/</link>
                <guid isPermaLink="false">66bc54f473c9920bb20c0e53</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Tue, 27 Apr 2021 18:12:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/04/random_user.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will build a React application using class components. Then we'll convert it to functional components using React Hooks in a step-by-step way.</p>
<p>By building this app, you will learn:</p>
<ul>
<li>How to make API calls</li>
<li>How to implement load more functionality</li>
<li>How to debug application issues</li>
<li>How to use async/await</li>
<li>How to update the component when something changes</li>
<li>How to fix the infinite loop issue in the useEffect hook</li>
<li>How to refactor class-based components into functional components with Hooks</li>
</ul>
<p>and much more.</p>
<p>So let’s get started.</p>
<blockquote>
<p>Want to learn Redux from the absolute beginning and build a food ordering app from scratch? Check out my <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
</blockquote>
<h2 id="heading-initial-project-setup">Initial Project Setup</h2>
<p>Create a new project using <code>create-react-app</code>:</p>
<pre><code>npx create-react-app <span class="hljs-class"><span class="hljs-keyword">class</span>-<span class="hljs-title">to</span>-<span class="hljs-title">hooks</span>-<span class="hljs-title">refactoring</span></span>
</code></pre><p>Once the project is created, delete all files from the <code>src</code> folder and create the <code>index.js</code> file and the <code>styles.css</code> file inside the <code>src</code> folder. Also, create a <code>components</code> folders inside the <code>src</code> folder.</p>
<p>Install the <code>axios</code> library by executing the following command from the project folder:</p>
<pre><code>yarn add axios@<span class="hljs-number">0.21</span><span class="hljs-number">.1</span>
</code></pre><p>Open the <code>styles.css</code> file and add the contents from <a target="_blank" href="https://github.com/myogeshchavan97/class-to-hooks-refactoring/blob/master/src/styles.css">this GitHub repo</a> to it.</p>
<h2 id="heading-how-to-create-the-initial-pages">How to Create the Initial Pages</h2>
<p>Create a new file called <code>Header.js</code> inside the <code>components</code> folder with the following content:</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> Header = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span>Random Users<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Header;
</code></pre>
<p>Create a new file called <code>App.js</code> inside the <code>src</code> folder with the following content:</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> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</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">React</span>.<span class="hljs-title">Component</span> </span>{
  render() {
    <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">"main-section"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>App Component<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, open the <code>index.js</code> file and add the following content to it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./styles.css'</span>;

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>Now, start the application by running the <code>yarn start</code> command from the terminal.</p>
<p>You will see the following screen if you access the application at <a target="_blank" href="http://localhost:3000/">http://localhost:3000/</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/index_page.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-make-an-api-call">How to Make an API Call</h2>
<p>We will be using the <a target="_blank" href="https://randomuser.me/">Random Users</a> API to get a list of random users.</p>
<p>So open your <code>App.js</code> file and add the <code>componentDidMount</code> method inside the component:</p>
<pre><code class="lang-js">componentDidMount() {
    axios
      .get(<span class="hljs-string">'https://randomuser.me/api/?page=0&amp;results=10'</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(response.data);
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error));
  }
</code></pre>
<p>Also, import <code>axios</code> at the top of the file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre>
<p>Your entire <code>App.js</code> file will look like this now:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</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">React</span>.<span class="hljs-title">Component</span> </span>{
  componentDidMount() {
    axios
      .get(<span class="hljs-string">'https://randomuser.me/api/?page=0&amp;results=10'</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(response.data);
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error));
  }

  render() {
    <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">"main-section"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>App Component<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>Here, we're making an API call to get a list of 10 records initially to the URL <code>https://randomuser.me/api/?page=0&amp;results=10</code>.</p>
<p>Now, if you check the application, you will see the response from the API in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/result-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, let's declare a state to store the result and flags related to the loading and error messages.</p>
<p>Replace the contents of <code>App.js</code> with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</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">React</span>.<span class="hljs-title">Component</span> </span>{
  state = {
    <span class="hljs-attr">users</span>: [],
    <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
  };

  componentDidMount() {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
    axios
      .get(<span class="hljs-string">'https://randomuser.me/api/?page=0&amp;results=10'</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
         <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">users</span>: response.data.results, <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span> });
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span>
        <span class="hljs-built_in">this</span>.setState({
          <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">'Error while loading data. Try again later.'</span>
        })
      )
      .finally(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
      });
  }

  render() {
    <span class="hljs-keyword">const</span> { users, isLoading, errorMsg } = <span class="hljs-built_in">this</span>.state;
    <span class="hljs-built_in">console</span>.log(users);

    <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">"main-section"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        {isLoading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loading"</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}
</code></pre>
<p>Here, we've declared a state directly inside the class using <a target="_blank" href="https://javascript.plainenglish.io/how-to-write-clean-and-easy-to-understand-react-code-using-class-properties-syntax-5b375b0618d3?source=friends_link&amp;sk=c170992cab9025fddb7b34b8894ea993">class properties syntax</a> which is a common way to write state in class-based components.</p>
<pre><code class="lang-js">state = {
  <span class="hljs-attr">users</span>: [],
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
};
</code></pre>
<p>Then, inside the <code>componentDidMount</code> method, we're first setting the <code>isLoading</code> state to <code>true</code> before making the API call.</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
</code></pre>
<p>Once we get the API response, we're storing the result in the <code>users</code> array which is declared in the state. We're also setting the <code>errorMsg</code> state to empty, so that if there are any previous errors they will be cleared out.</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">users</span>: response.data.results, <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span> });
</code></pre>
<p>And in the <code>.catch</code> block, we're setting the <code>errorMsg</code> in case there is any error while making an API call.</p>
<p>Then, we're using the <code>.finally</code> block to set the <code>isLoading</code> state to <code>false</code>.</p>
<pre><code class="lang-js">.finally(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
});
</code></pre>
<p>Using <code>finally</code> helps us avoid code duplication here because we don't need to set <code>isLoading</code> to <code>false</code> in <code>.then</code> and in the <code>.catch</code> block again. This is because the <code>finally</code> block will always be executed whether it's successful or not.</p>
<p>And in the render method, we're displaying either the error message or loading message along with the <code>users</code> array from the state in the console.</p>
<p>Now, if you check the application, you will see the <code>users</code> information in the console on success or an error message on the UI for API failure.</p>
<h2 id="heading-how-to-display-the-users-information">How to Display the Users Information</h2>
<p>Now, let's display the <code>users</code> information on the screen.</p>
<p>Create a new file <code>User.js</code> inside the <code>components</code> folder with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> User = <span class="hljs-function">(<span class="hljs-params">{ name, location, email, picture }</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">"random-user"</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-image"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{picture.medium}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{name.first}</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">"user-details"</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">strong</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> {name.first} {name.last}
        <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">strong</span>&gt;</span>Country:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> {location.country}
        <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">strong</span>&gt;</span>Email:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> {email}
        <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> User;
</code></pre>
<p>Now, create a new file <code>UsersList.js</code> inside the <code>components</code> folder with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">'./User'</span>;

<span class="hljs-keyword">const</span> UsersList = <span class="hljs-function">(<span class="hljs-params">{ users }</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">"user-list"</span>&gt;</span>
      {users &amp;&amp; users.map((user) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">User</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{user.login.uuid}</span> {<span class="hljs-attr">...user</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> UsersList;
</code></pre>
<p>Now, open the <code>App.js</code> file and replace the <code>render</code> method with the following code:</p>
<pre><code class="lang-js">render() {
  <span class="hljs-keyword">const</span> { users, isLoading, errorMsg } = <span class="hljs-built_in">this</span>.state;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      {isLoading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loading"</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here, we're passing the <code>users</code> array as a prop to the <code>UsersList</code> component. Inside the <code>UsersList</code> component, we're looping over the array and sending the user information to the <code>User</code> component by spreading out all the properties of the individual <code>user</code> as <code>{...props}</code>. This finally displays the data on the screen.</p>
<p>Also, import the <code>UsersList</code> component at the top of the file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> UsersList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/UsersList'</span>;
</code></pre>
<p>If you check the application now, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/random_users.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, on every page refresh, a new set of random users is displayed on the screen.</p>
<h2 id="heading-how-to-add-the-load-more-functionality">How to Add the Load More Functionality</h2>
<p>Now, let's add the load more functionality which will let our app load the next set of 10 users on every load more click.</p>
<p>Change the <code>render</code> method of the <code>App.js</code> file to the following code:</p>
<pre><code class="lang-js">render() {
  <span class="hljs-keyword">const</span> { users, isLoading, errorMsg } = <span class="hljs-built_in">this</span>.state;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
      {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"load-more"</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.loadMore}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"btn-grad"</span>&gt;</span>
          {isLoading ? 'Loading...' : 'Load More'}
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here, we've added the <code>isLoading</code> check inside the button to display either the <code>Loading...</code> or <code>Load More</code> text on the button.</p>
<p>Add a new <code>page</code> property to the state and initialize it to <code>0</code>.</p>
<pre><code class="lang-js">state = {
  <span class="hljs-attr">users</span>: [],
  <span class="hljs-attr">page</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
};
</code></pre>
<p>And add the <code>loadMore</code> handler function before the <code>render</code> method to increment the <code>page</code> state value by 1 on every button click.</p>
<pre><code class="lang-js">loadMore = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
    <span class="hljs-attr">page</span>: prevState.page + <span class="hljs-number">1</span>
  }));
};
</code></pre>
<p>Here, we're using the previous state to calculate the next state value of the page, so the above code is the same as the below code:</p>
<pre><code class="lang-js">loadMore = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">page</span>: prevState.page + <span class="hljs-number">1</span>
    };
  });
};
</code></pre>
<p>We're just using ES6 shorthand syntax for returning an object from the function.</p>
<p>Now, inside the <code>componentDidMount</code> method, change the API URL from the below code:</p>
<pre><code class="lang-js"><span class="hljs-string">'https://randomuser.me/api/?page=0&amp;results=10'</span>
</code></pre>
<p>to this code:</p>
<pre><code class="lang-js"><span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>
</code></pre>
<p>Here, we're using the ES6 template literal syntax to use the dynamic value of the <code>page</code> state to load the next set of users on every button click.</p>
<p>Destructure the <code>page</code> from state inside the <code>componentDidMount</code> method like this:</p>
<pre><code class="lang-js">componentDidMount() {
  <span class="hljs-keyword">const</span> { page } = <span class="hljs-built_in">this</span>.state;
  ....
}
</code></pre>
<blockquote>
<p>Want to explore all the ES6+ features in detail? Check out my <a target="_blank" href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a> book.</p>
</blockquote>
<p>Now, let's check the application's functionality.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/load_more_state_changing.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, when we click on the <code>Load More</code> button, the <code>page</code> state is changing in the react dev tools but we're not getting the new list of users displayed on the screen.</p>
<p>This is because even though we're changing the <code>page</code> state, we're not making API call again to get the next set of users with the changed <code>page</code> value. So let's fix this.</p>
<p>Create a new <code>loadUsers</code> function above the <code>loadMore</code> function and move all the code from <code>componentDidMount</code> to inside the <code>loadUsers</code> function. Then call the <code>loadUsers</code> function from the <code>componentDidMount</code> method.</p>
<p>Also, add a <code>componentDidUpdate</code> method inside the <code>App</code> component like this:</p>
<pre><code class="lang-js">componentDidUpdate(prevProps, prevState) {
  <span class="hljs-keyword">if</span> (prevState.page !== <span class="hljs-built_in">this</span>.state.page) {
    <span class="hljs-built_in">this</span>.loadUsers();
  }
}
</code></pre>
<p>As we're updating the value of the <code>page</code> state in the <code>loadMore</code> function once the state is updated, the <code>componentDidUpdate</code> method will be called. So we're checking if the previous state value of <code>page</code> is not equal to the current state value. Then we make the API call again by calling the <code>loadUsers</code> function.</p>
<blockquote>
<p>Check out my <a target="_blank" href="https://www.freecodecamp.org/news/what-is-state-in-react-explained-with-examples/">previous article</a> to learn more about why and when we need to use the <code>componentDidUpdate</code> method.</p>
</blockquote>
<p>Your complete <code>App.js</code> file will look like this now:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> UsersList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/UsersList'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</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">React</span>.<span class="hljs-title">Component</span> </span>{
  state = {
    <span class="hljs-attr">users</span>: [],
    <span class="hljs-attr">page</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
  };

  componentDidMount() {
    <span class="hljs-built_in">this</span>.loadUsers();
  }

  componentDidUpdate(prevProps, prevState) {
    <span class="hljs-keyword">if</span> (prevState.page !== <span class="hljs-built_in">this</span>.state.page) {
      <span class="hljs-built_in">this</span>.loadUsers();
    }
  }

  loadUsers = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { page } = <span class="hljs-built_in">this</span>.state;

    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
    axios
      .get(<span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">users</span>: response.data.results, <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span> });
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span>
        <span class="hljs-built_in">this</span>.setState({
          <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">'Error while loading data. Try again later.'</span>
        })
      )
      .finally(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
      });
  };

  loadMore = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
      <span class="hljs-attr">page</span>: prevState.page + <span class="hljs-number">1</span>
    }));
  };

  render() {
    <span class="hljs-keyword">const</span> { users, isLoading, errorMsg } = <span class="hljs-built_in">this</span>.state;

    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main-section"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
        {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"load-more"</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.loadMore}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"btn-grad"</span>&gt;</span>
            {isLoading ? 'Loading...' : 'Load More'}
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}
</code></pre>
<p>Now, if you check the application again by running the <code>yarn start</code> command you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/new_users_loaded.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we're getting a new list of users displayed on every load more button click. But the issue is that we're only able to see 10 users at a time.</p>
<p>So let's make changes to add new users to the already displayed list of users.</p>
<p>For this, we need to change the way we're setting the <code>users</code> state.</p>
<p>Our current <code>setState</code> call inside the <code>loadUsers</code> function looks like this:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">users</span>: response.data.results, <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span> });
</code></pre>
<p>Here, we're always replacing the <code>users</code> array with the new set of users. So change the above <code>setState</code> call to the following code:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
  <span class="hljs-attr">users</span>: [...prevState.users, ...response.data.results],
  <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
}));
</code></pre>
<p>Here, we're using the updater syntax of <code>setState</code>. We're creating a new array by spreading out the already added <code>users</code> by using <code>...prevState.users</code>, and then we're adding a new set of <code>users</code> by using <code>...response.data.results</code>.</p>
<p>So this way we'll not lose the previous loaded <code>users</code> data and we'll also be able to append a new set of <code>users</code>.</p>
<p>Now, if you check the application again, you will see the correct behavior of data loading.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/correct_loading.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-improve-the-code-using-asyncawait">How to Improve the Code using Async/await</h2>
<p>If you check the <code>loadUsers</code> function, you will see that the code looks complex and difficult to read.</p>
<pre><code class="lang-js">loadUsers = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { page } = <span class="hljs-built_in">this</span>.state;

  <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
  axios
    .get(<span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>)
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
      <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
        <span class="hljs-attr">users</span>: [...prevState.users, ...response.data.results],
        <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
      }));
    })
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span>
      <span class="hljs-built_in">this</span>.setState({
        <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">'Error while loading data. Try again later.'</span>
      })
    )
    .finally(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
    });
};
</code></pre>
<p>We can fix this using async/await syntax.</p>
<p>First, we need to mark the <code>loadUsers</code> function as async:</p>
<pre><code class="lang-js">loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
</code></pre>
<p>Because we can use the <code>await</code> keyword only inside the function which is declared as <code>async</code>.</p>
<p>Now, replace the <code>loadUsers</code> function with the following code:</p>
<pre><code class="lang-js">loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { page } = <span class="hljs-built_in">this</span>.state;

    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(
      <span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>
    );

    <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
      <span class="hljs-attr">users</span>: [...prevState.users, ...response.data.results],
      <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
    }));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">this</span>.setState({
      <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">'Error while loading data. Try again later.'</span>
    });
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
  }
};
</code></pre>
<p>Here, we've used the <code>await</code> keyword before the <code>axios.get</code> call so the next line of code which is the <code>setState</code> call will not be executed until we get the response from the API.</p>
<p>If there is any error while getting the response from the API, the <code>catch</code> block will be executed. The <code>finally</code> block will set the <code>isLoading</code> state to <code>false</code>.</p>
<p>Your changed <code>App.js</code> file will look like this now:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> UsersList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/UsersList'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</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">React</span>.<span class="hljs-title">Component</span> </span>{
  state = {
    <span class="hljs-attr">users</span>: [],
    <span class="hljs-attr">page</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
  };

  componentDidMount() {
    <span class="hljs-built_in">this</span>.loadUsers();
  }

  componentDidUpdate(prevProps, prevState) {
    <span class="hljs-keyword">if</span> (prevState.page !== <span class="hljs-built_in">this</span>.state.page) {
      <span class="hljs-built_in">this</span>.loadUsers();
    }
  }

  loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { page } = <span class="hljs-built_in">this</span>.state;

      <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span> });
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>
      );

      <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
        <span class="hljs-attr">users</span>: [...prevState.users, ...response.data.results],
        <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">''</span>
      }));
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">this</span>.setState({
        <span class="hljs-attr">errorMsg</span>: <span class="hljs-string">'Error while loading data. Try again later.'</span>
      });
    } <span class="hljs-keyword">finally</span> {
      <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> });
    }
  };

  loadMore = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
      <span class="hljs-attr">page</span>: prevState.page + <span class="hljs-number">1</span>
    }));
  };

  render() {
    <span class="hljs-keyword">const</span> { users, isLoading, errorMsg } = <span class="hljs-built_in">this</span>.state;

    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main-section"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
        {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"load-more"</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.loadMore}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"btn-grad"</span>&gt;</span>
            {isLoading ? 'Loading...' : 'Load More'}
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}
</code></pre>
<p>Now, the <code>loadUsers</code> function code looks much cleaner and easier to understand than it was before. And if you check the application, you will see that the application is also working correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/correct_loading-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-refactor-class-component-code-to-functional-component-code">How to Refactor Class Component Code to Functional Component Code</h2>
<p>We're done building out the complete functionality of the app. So let's refactor the code to use functional components with React Hooks.</p>
<blockquote>
<p>If you're new to React Hooks, check out <a target="_blank" href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe?source=friends_link&amp;sk=89baff89ec8bc637e7c13b7554904e54">my article here</a> for an introduction to Hooks.</p>
</blockquote>
<p>Create a new file called <code>AppFunctional.js</code> inside the <code>src</code> folder with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> AppFunctional = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Functional Component<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> AppFunctional;
</code></pre>
<p>We've created a new file for the functional component so you will be able to compare both the code and keep it for your reference.</p>
<p>Now, open the <code>index.js</code> file and replace the contents of the file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> AppFunctional <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppFunctional'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./styles.css'</span>;

ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AppFunctional</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
</code></pre>
<p>Here, we've used the <code>AppFunctional</code> component inside the <code>render</code> method and we've also added the import for the same at the top of the file.</p>
<p>Now, if you restart your application using the <code>yarn start</code> command you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/functional_component.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So we're correctly displaying the <code>AppFunctional</code> component code on the screen.</p>
<p>Now, replace the contents of the<code>AppFunctional</code> component with the following code:</p>
<pre><code class="lang-js"><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> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
<span class="hljs-keyword">import</span> UsersList <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/UsersList'</span>;

<span class="hljs-keyword">const</span> AppFunctional = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [users, setUsers] = useState([]);
  <span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [errorMsg, setErrorMsg] = useState(<span class="hljs-string">''</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        setIsLoading(<span class="hljs-literal">true</span>);
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(
          <span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>
        );

        setUsers([...users, ...response.data.results]);
        setErrorMsg(<span class="hljs-string">''</span>);
      } <span class="hljs-keyword">catch</span> (error) {
        setErrorMsg(<span class="hljs-string">'Error while loading data. Try again later.'</span>);
      } <span class="hljs-keyword">finally</span> {
        setIsLoading(<span class="hljs-literal">false</span>);
      }
    };

    loadUsers();
  }, []);

  <span class="hljs-keyword">const</span> loadMore = <span class="hljs-function">() =&gt;</span> {
    setPage(<span class="hljs-function">(<span class="hljs-params">page</span>) =&gt;</span> page + <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">"main-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
      {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"load-more"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{loadMore}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"btn-grad"</span>&gt;</span>
          {isLoading ? 'Loading...' : 'Load More'}
        <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> AppFunctional;
</code></pre>
<p>Here, we've initially declared the required states using the <code>useState</code> hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [users, setUsers] = useState([]);
<span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">0</span>);
<span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
<span class="hljs-keyword">const</span> [errorMsg, setErrorMsg] = useState(<span class="hljs-string">''</span>);
</code></pre>
<p>Then we've added a <code>useEffect</code> hook and passed an empty array <code>[]</code> as the second argument to it. This means that the code inside the <code>useEffect</code> hook will be executed only once when the component is mounted.</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
 <span class="hljs-comment">// your code</span>
}, []);
</code></pre>
<p>We've moved the entire <code>loadUsers</code> function inside the <code>useEffect</code> hook and then called it inside the hook like this:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// your code</span>
  };

  loadUsers();
}, []);
</code></pre>
<p>We've also removed all the references to <code>this.state</code> as functional components don't need <code>this</code> context.</p>
<p>Before making the API call, we're setting the <code>isLoading</code> state to <code>true</code> using <code>setIsLoading(true);</code>.</p>
<p>As we already have access to the <code>users</code> array inside the component, we're directly setting as a new array for the <code>setUsers</code> function like this:</p>
<pre><code class="lang-js">setUsers([...users, ...response.data.results]);
</code></pre>
<blockquote>
<p>If you want to know why we can't use the <code>async</code> keyword directly for the <code>useEffect</code> hook function, check out <a target="_blank" href="https://javascript.plainenglish.io/handling-api-calls-using-async-await-in-useeffect-hook-990fb4ae423?source=friends_link&amp;sk=dd686f066a434c41a76c352e3ec69767">this article</a>.</p>
</blockquote>
<p>Then we've changed the <code>loadMore</code> function from the below code:</p>
<pre><code class="lang-js">loadMore = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">prevState</span>) =&gt;</span> ({
    <span class="hljs-attr">page</span>: prevState.page + <span class="hljs-number">1</span>
  }));
};
</code></pre>
<p>to this code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> loadMore = <span class="hljs-function">() =&gt;</span> {
  setPage(<span class="hljs-function">(<span class="hljs-params">page</span>) =&gt;</span> page + <span class="hljs-number">1</span>);
};
</code></pre>
<blockquote>
<p>Note that to declare a function in functional components you need to add <code>const</code> or <code>let</code> before the declaration. As the function is not going to change, it's recommended to use <code>const</code> such as <code>const loadMore = () =&gt; { }</code>.</p>
</blockquote>
<p>Then we've copied the <code>render</code> method content as it is inside the <code>AppFunctional</code> component for returning the JSX. We've also changed <code>onClick={this.loadMore}</code> to <code>onClick={loadMore}</code>.</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">"main-section"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">UsersList</span> <span class="hljs-attr">users</span>=<span class="hljs-string">{users}</span> /&gt;</span>
    {errorMsg &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorMsg"</span>&gt;</span>{errorMsg}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"load-more"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{loadMore}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"btn-grad"</span>&gt;</span>
        {isLoading ? 'Loading...' : 'Load More'}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>Now, if you check the application, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/functional_load_more_not_working.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, the users are correctly getting loaded, but the load more functionality does not work.</p>
<p>This is because we're only making the API call once when the component is mounted as we're passing the empty dependency array <code>[]</code> as the second argument to the <code>useEffect</code> hook.</p>
<p>To make the API call again when the <code>page</code> state changes, we need to add the <code>page</code> as a dependency for the <code>useEffect</code> hook like this:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// execute the code to load users</span>
}, [page]);
</code></pre>
<p>The above <code>useEffect</code> is the same as writing the below code:</p>
<pre><code class="lang-js">componentDidUpdate(prevProps, prevState) {
  <span class="hljs-keyword">if</span> (prevState.page !== <span class="hljs-built_in">this</span>.state.page) {
    <span class="hljs-comment">// execute the code to load users</span>
  }
}
</code></pre>
<p><code>useEffect</code> makes it really easy to write less code that is easy to understand.</p>
<p>So now with this change, the code inside the <code>useEffect</code> hook will be executed when the component mounts as well as when the <code>page</code> state is changed.</p>
<p>Now, if you check the application, you will see that the load more functionality is working again as expected.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/correct_loading-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>But if you check the terminal/command prompt, you might see a warning as shown below (if you have <code>ESLint</code> installed on your machine):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/eslint_warning.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>These warnings help us avoid issues in our application that might occur later, so it's always good to fix them if possible.</p>
<p>As we're referencing the <code>users</code> state inside the <code>loadUsers</code> function, we need to include that also in the dependency array. So let's do that.</p>
<p>Include the <code>users</code> as a dependency along with the <code>page</code> like this:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// your code</span>
}, [page, users]);
</code></pre>
<p>Let's check the application functionality now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/infinite_loop.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we're continuously getting a new set of users as we scroll the page and the application is going in an infinite loop.</p>
<p>This is because when the component is mounted, the code inside the <code>useEffect</code> hook will be executed to make an API call. Once we get the result, we're setting the <code>users</code> array. </p>
<p>As <code>users</code> is mentioned in the dependencies list, once the <code>users</code> array is changed, <code>useEffect</code> will run again and it will happen again and again creating an infinite loop.</p>
<p>So to fix this, we need to avoid referencing the external <code>users</code> array somehow. To do that, let's use the updater syntax of set state to set the <code>users</code> state.</p>
<p>Therefore, change the below code:</p>
<pre><code class="lang-js">setUsers([...users, ...response.data.results]);
</code></pre>
<p>to this code:</p>
<pre><code class="lang-js">setUsers(<span class="hljs-function">(<span class="hljs-params">users</span>) =&gt;</span> [...users, ...response.data.results]);
</code></pre>
<p>Here, we're using the previous value of users to create a new <code>users</code> array.</p>
<p>Now, we can remove the <code>users</code> from the <code>useEffect</code> dependencies array as we're not referencing the external <code>users</code> variable.</p>
<p>Your changed <code>useEffect</code> hook will look like this now:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> loadUsers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      setIsLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(
        <span class="hljs-string">`https://randomuser.me/api/?page=<span class="hljs-subst">${page}</span>&amp;results=10`</span>
      );

      setUsers(<span class="hljs-function">(<span class="hljs-params">users</span>) =&gt;</span> [...users, ...response.data.results]);
      setErrorMsg(<span class="hljs-string">''</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      setErrorMsg(<span class="hljs-string">'Error while loading data. Try again later.'</span>);
    } <span class="hljs-keyword">finally</span> {
      setIsLoading(<span class="hljs-literal">false</span>);
    }
  };

  loadUsers();
}, [page]);
</code></pre>
<p>If you check the application now, you will see that the application is working as expected without any issues.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/correct_loading-3.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And we're also not getting any errors in the terminal now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/no_error.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>You can find the complete source code for this application in <a target="_blank" href="https://github.com/myogeshchavan97/class-to-hooks-refactoring">this repository</a> and a live demo of the deployed application <a target="_blank" href="https://random-users-app.netlify.app/">here</a>.</p>
<p>Starting with ES6, there are many useful additions to JavaScript like:</p>
<ul>
<li>ES6 Destructuring</li>
<li>Import and Export Syntax</li>
<li>Arrow functions</li>
<li>Promises</li>
<li>Async/await</li>
<li>Optional chaining operator and a lot more.</li>
</ul>
<p><strong>You can learn everything about all the ES6+ features in detail in my <a target="_blank" href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a> book.</strong></p>
<blockquote>
<p>Check out free preview contents of the book <a target="_blank" href="https://www.freecodecamp.org/news/learn-modern-javascript/">here</a>.</p>
</blockquote>
<p>Also, you can check out my <strong>free</strong> <a target="_blank" href="https://yogeshchavan1.podia.com/react-router-introduction">Introduction to React Router</a> course to learn React Router from scratch.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
<p><a href="https://bit.ly/3w0DGum" target="_blank"><img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg" width="600" height="400" alt="banner" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy a React Router-Based Application to Netlify ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll learn the most popular ways of deploying a React app to Netlify. We'll also learn the configuration changes you'll need to make to deploy a Routing-based React app. The thing I love about Netlify is that it provides a lot of us... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-react-router-based-app-to-netlify/</link>
                <guid isPermaLink="false">66bc5519d94fa6cb67b844ff</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Netlify ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react router ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yogesh Chavan ]]>
                </dc:creator>
                <pubDate>Mon, 19 Apr 2021 21:38:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/04/routing.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll learn the most popular ways of deploying a React app to Netlify. We'll also learn the configuration changes you'll need to make to deploy a Routing-based React app.</p>
<p>The thing I love about <a target="_blank" href="https://www.netlify.com/">Netlify</a> is that it provides a lot of useful features<br>for free such as:</p>
<ul>
<li>A way to deploy a static website within seconds</li>
<li>Continuous deployment, which means when you connect your Github/Gitlab/Bitbucket repository, it automatically triggers deployment when new commits are pushed to the repository</li>
<li>Assurance that your website never goes down, even during new deployments</li>
<li>Allows you to easily rollback to any previous working version of your site with a single click</li>
<li>Lets you quickly preview any of the previously deployed versions of the app</li>
<li>Change the domain or subdomain of your site instantly </li>
</ul>
<p>and much more.</p>
<p>So let's see how to deploy a React app to Netlify.</p>
<blockquote>
<p>Want to learn Redux from the absolute beginning and build a food ordering app from scratch? Check out the <a target="_blank" href="https://master-redux.yogeshchavan.dev/">Mastering Redux</a> course.</p>
</blockquote>
<h2 id="heading-drag-and-drop-the-build-folder-in-netlify">Drag and Drop the Build Folder in Netlify</h2>
<p>The fastest and easy way to deploy a React application is just to drag and drop the build folder in Netlify.</p>
<p>To create a build folder, just execute the <code>npm run build</code> or <code>yarn build</code> command from the command line from your project folder.</p>
<p>Once the build folder is created, you just need to drop the folder in the drop area under the <code>sites</code> menu, as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/drag_drop.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-deploy-an-app-to-netlify-from-a-github-repository">How to Deploy an App to Netlify from a GitHub Repository</h2>
<p>This is my favorite way of deploying applications on Netlify.</p>
<p>Because whenever you push any changes to the GitHub repository, it will automatically be deployed to Netlify. You can also see all deployed versions and easily roll back to any previously working version of code with just a single click.</p>
<p>If you already have a repository pushed to GitHub, then you just need to connect it.</p>
<p>Login to your Netlify account. In the dashboard, click on the <code>New site from Git</code> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/netlify_home.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click on the <code>GitHub</code> button to connect your GitHub repository.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/git_provider.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It will open a new tab. Make sure the popup is enabled in your browser.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/select_repository.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Search for the GitHub repository in the <code>Search repos</code> search box. If your repository is not getting displayed then click on the <code>Configure the Netlify app on GitHub</code> button at the bottom of the page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/configure_netlify.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once clicked, scroll down on the page and click on the <code>Select repositories</code> dropdown and search for your repository and click on the <code>Save</code> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/select_repo.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will be redirected to the previous page showing all the available repositories.</p>
<p>Search for the repository you want to deploy. For this article, I have selected the <a target="_blank" href="https://github.com/myogeshchavan97/react-book-management-app">react-book-management-app</a> repository which we created in my <a target="_blank" href="https://www.freecodecamp.org/news/react-crud-app-how-to-create-a-book-management-app-from-scratch/">previous article</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/find_repository-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once you select the repository, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/deploy_repository.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For this application, we don't need to change anything.</p>
<p>Your <code>Build command</code> and <code>Publish directory</code> will be automatically populated. Make sure to enter these fields if you have a different command in <code>package.json</code> to build your app or those fields are not auto-populated. </p>
<p>Now, click on the <code>Deploy site</code> button. Once clicked, you will see the <code>Site deploy in progress</code> message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/deploying.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You'll have to wait a little bit while it's deploying. Once deployment is completed, you will see the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/deployed.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Open the link in the new tab and you will see your application deployed live.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/deployed_app.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Awesome! Now, if you make any changes in the source code and push that change to GitHub, Netlify will detect that change and re-deploy your application with your latest changes.</p>
<p>If you check the application, you will see that the application works just fine with the navigation and you're able to add/edit/delete a book.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/working_app.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>But there is one issue.</strong> If you directly access the <code>/add</code> route or refresh the <code>/add</code> route page, you will get a page not found error as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/page_not_found.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will get the same error if you try to refresh the edit page route.</p>
<p>This is because when we access any route on our local machine, React Router handles the routing. But when we deploy the application on any server, directly accessing the route will send the request to the server itself (Netlify in our case).</p>
<p>But as there is no <code>/add</code> route handler on the server-side, you will see a page not found error. But Netlify provides a way to fix this.</p>
<p>Create a new file with the name <code>_redirects</code> inside the <code>public</code> folder of our project and add the following contents inside it:</p>
<pre><code class="lang-js"><span class="hljs-comment">/* /index.html 200</span>
</code></pre>
<p>Here, we're telling Netlify to redirect all the routes to the <code>index.html</code> file. </p>
<p>The <code>index.html</code> file contains our entire React app code. It gets generated inside the <code>build</code> folder when the <code>yarn build</code> command is executed by Netlify while deploying the app.</p>
<p>And as routing is handled by our React app which is contained in the <code>index.html</code> file, our application will work without a page not found issue.</p>
<p>Now, push the changes to the GitHub repository so Netlify will deploy the app again with these changes.</p>
<p>And once deployed, if you check the deployed application, you will see that the application works fine and we don't get a page not found error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/no_page_not_found.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That's it! We're all done with deploying our application to Netlify.</p>
<h2 id="heading-how-to-easily-change-a-site-name-in-netlify">How to Easily Change a Site Name in Netlify</h2>
<p>If you check the name of the deployed site you will see that it's not easy to remember, especially if you have lot of applications deployed. But Netlify provides a way to easily change that.</p>
<p>Click on the <code>Site settings</code> button displayed on the <code>Site overview</code> section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/site_settings.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then click on the <code>Change site name</code> button and enter a new name. Click on the <code>Save</code> button, and now you can access your application with the changed name.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/changed_site_name.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<blockquote>
<p>I usually like to give the same name as the repository name so it's easy to find a particular application if you have a lot of deployed applications on Netlify.</p>
</blockquote>
<p>If you want to know how to deploy React + Node.js application to production, check out <a target="_blank" href="https://dev.to/myogeshchavan97/how-to-deploy-react-node-js-application-to-heroku-4jb4">this article</a>.</p>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>You can find the complete GitHub source code along with this redirection change in <a target="_blank" href="https://github.com/myogeshchavan97/netlify-react-book-management-app">this repository</a>.</p>
<p><strong>You can see the live demo of the deployed application <a target="_blank" href="https://react-book-management-app.netlify.app/">here</a>.</strong></p>
<p>Want to learn all ES6+ features in detail including let and const, promises, various promise methods, array and object destructuring, arrow functions, async/await, import and export and a whole lot more from scratch?</p>
<p>Check out my <a target="_blank" href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a> book. This book covers all the pre-requisites for learning React and helps you to become better at JavaScript and React.</p>
<blockquote>
<p>Check out free preview contents of the book <a target="_blank" href="https://www.freecodecamp.org/news/learn-modern-javascript/">here</a>.</p>
</blockquote>
<p>Also, you can check out my <strong>free</strong> <a target="_blank" href="https://yogeshchavan1.podia.com/react-router-introduction">Introduction to React Router</a> course to learn React Router from scratch.</p>
<p>Want to stay up to date with regular content regarding JavaScript, React, Node.js? <a target="_blank" href="https://www.linkedin.com/in/yogesh-chavan97/">Follow me on LinkedIn</a>.</p>
<p><a href="https://bit.ly/3w0DGum" target="_blank"><img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg" width="600" height="400" alt="banner" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
