<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: L Javier Tovar</title>
    <description>The latest articles on Forem by L Javier Tovar (@ljaviertovar).</description>
    <link>https://forem.com/ljaviertovar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F964146%2F4501a361-6dd8-46a7-ae8e-06037ca35e91.jpg</url>
      <title>Forem: L Javier Tovar</title>
      <link>https://forem.com/ljaviertovar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ljaviertovar"/>
    <language>en</language>
    <item>
      <title>How to hide your API keys and tokens in React to protect your application</title>
      <dc:creator>L Javier Tovar</dc:creator>
      <pubDate>Tue, 17 Jan 2023 15:23:43 +0000</pubDate>
      <link>https://forem.com/ljaviertovar/how-to-hide-your-api-keys-and-tokens-in-react-to-protect-your-application-1dmc</link>
      <guid>https://forem.com/ljaviertovar/how-to-hide-your-api-keys-and-tokens-in-react-to-protect-your-application-1dmc</guid>
      <description>&lt;h2&gt;
  
  
  Using environment variables in Reactjs with Vite and nodejs
&lt;/h2&gt;

&lt;p&gt;Have you ever noticed that some applications have API keys, tokens, or other sensitive credentials visible in their source code? or maybe your own applications?&lt;/p&gt;

&lt;p&gt;Well, this can be dangerous and put the security of your services at risk.&lt;/p&gt;

&lt;p&gt;API keys, tokens, and other sensitive credentials are used to authenticate and authorize access to services and APIs. If this data is exposed in your application’s source code, anyone who can see your code can access it and use it to perform unauthorized actions on your behalf.&lt;/p&gt;

&lt;p&gt;Moreover, by exposing your credentials, you are allowing third parties to use them, which can affect the performance or quality of your services, or even perform attacks against them.&lt;/p&gt;

&lt;p&gt;This tutorial will show us how to hide your API keys, tokens, and other sensitive credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to hide sensitive data?
&lt;/h2&gt;

&lt;p&gt;Some of the ways to do this are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use environment variables&lt;/li&gt;
&lt;li&gt;Use a proxy server or a backend platform as a service (BaaS)&lt;/li&gt;
&lt;li&gt;Use a secure hosting platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this way, you can protect the security of your services and prevent them from being compromised.&lt;/p&gt;

&lt;p&gt;Now, we will see how to hide sensitive credentials by building a small backend for our React application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Environment Variables in React with Vite
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will add an &lt;a href="https://openweathermap.org/" rel="noopener noreferrer"&gt;OpenWeather&lt;/a&gt; APY KEY as an environment variable.&lt;br&gt;
Specifically, we will use the &lt;a href="https://openweathermap.org/current" rel="noopener noreferrer"&gt;weather API&lt;/a&gt;, which is a service that provides weather data, and after a certain number of requests, it starts charging for the requests, so we don’t want this API KEY to be available to the public.&lt;/p&gt;

&lt;p&gt;To configure the environment variables in React with Vite we can follow the following steps:&lt;/p&gt;

&lt;p&gt;1 — Create your React application with Vite. I will use TypeScript but you can use JavaScript if you wish.&lt;/p&gt;

&lt;p&gt;2 — Create a &lt;code&gt;.env&lt;/code&gt; file at the root of your project. This file should contain the environment variables you want to use in your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;784dc6d4eXXXXXXXXb14460d3a356565
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we create our &lt;code&gt;.env&lt;/code&gt; file we must not forget to attach it to the &lt;code&gt;.gitignore&lt;/code&gt; file of git, otherwise, our &lt;code&gt;API KEY&lt;/code&gt; will be exposed in the repository.&lt;/p&gt;

&lt;p&gt;3— In Vite, to access the environment variables we need to access them via import.meta.env. This returns an object containing the available environment variables known to Vite.&lt;/p&gt;

&lt;p&gt;The variables created must have the prefix &lt;code&gt;VITE_&lt;/code&gt; or could be another prefix overwriting the default configuration option &lt;a href="https://vitejs.dev/config/shared-options.html#envprefix" rel="noopener noreferrer"&gt;envPrefix&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 — Now we will create a simple application that will fetch the Weather API to retrieve the temperature of a city.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ResponseWeather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_KEY&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWeather&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ResponseWeather&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://api.openweathermap.org/data/2.5/weather?lat=43.7001&amp;amp;lon=-79.4163&amp;amp;appid=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;setWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;273.15&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="err"&gt;°&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
       &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`http://openweathermap.org/img/wn/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@2x.png`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qiiv08x624yq2o0ehhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qiiv08x624yq2o0ehhm.png" alt="Fetch Weather API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have hidden our &lt;code&gt;API KEY&lt;/code&gt; with an environment variable and made sure that the .env file is not uploaded to the repository we have done half the work.&lt;/p&gt;

&lt;p&gt;And why do we say this? Because our &lt;code&gt;API KEY&lt;/code&gt; is still exposed in the final build, if we inspect our app in the browser we will find the value of the &lt;code&gt;API KEY&lt;/code&gt;, so the only way to have this value completely hidden is to have it on the server side creating a backend service.&lt;/p&gt;

&lt;p&gt;This backend will be in charge of making requests to the Openweather service and our client, that is, our React application will query this backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm express cors dotenv axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case that we use Typescript, we will need in addition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm ts-node @types/express @types/cors @types/dotenv @types/node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;express&lt;/a&gt; to create a server&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/expressjs/cors#readme" rel="noopener noreferrer"&gt;cors&lt;/a&gt; to enable resource sharing between different domains.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/motdotla/dotenv#readme" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt; to load environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://axios-http.com/" rel="noopener noreferrer"&gt;axios&lt;/a&gt; to fetch data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2 — We create a file called &lt;code&gt;api.ts&lt;/code&gt; at the root of the project. We also take the opportunity to add a new command to &lt;code&gt;package.json&lt;/code&gt; to boost our server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npx ts-node api.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 — We create the server and make available the endpoint that we will use from React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/weather&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://api.openweathermap.org/data/2.5/weather?lat=43.7001&amp;amp;lon=-79.4163&amp;amp;appid=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;axios&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the backend service, our &lt;code&gt;API KEY&lt;/code&gt; is completely hidden from the client. We could add more layers of security as we want for example, in the cors add only the domain where our app is hosted and only that domain can make requests.&lt;/p&gt;

&lt;p&gt;4 — We start our server with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm run server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we just need to replace the URL of the request we make in React with the one we have in the backend. We no longer need to retrieve the &lt;code&gt;API KEY&lt;/code&gt; in React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://api.openweathermap.org/data/2.5/weather?lat=43.7001&amp;amp;lon=-79.4163&amp;amp;appid=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
 &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3001/api/weather&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! our application continues to work as usual only that we no longer have our API KEY exposed on the client side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ljaviertovar/data-safe-react" rel="noopener noreferrer"&gt;Repo here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, hiding sensitive data is something relatively easy, just follow the steps mentioned above and with that, we can avoid major risks and complications.&lt;/p&gt;

&lt;p&gt;I hope this will help you to keep your projects safe.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/take-your-modals-to-the-next-level-how-to-create-reusable-and-customizable-modals-with-react-and-typescript-4555"&gt;How to create reusable and customizable modals with React and TypeScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/why-should-you-use-cleanup-functions-in-reacts-useeffect-hook-2g2c"&gt;Why Should You Use Cleanup Functions in React’s useEffect Hook?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to Connect?&lt;br&gt;
Love connecting with friends all around the world on &lt;a href="https://twitter.com/ljaviertovar" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to create reusable and customizable modals with React and TypeScript</title>
      <dc:creator>L Javier Tovar</dc:creator>
      <pubDate>Sun, 18 Dec 2022 02:14:58 +0000</pubDate>
      <link>https://forem.com/ljaviertovar/take-your-modals-to-the-next-level-how-to-create-reusable-and-customizable-modals-with-react-and-typescript-4555</link>
      <guid>https://forem.com/ljaviertovar/take-your-modals-to-the-next-level-how-to-create-reusable-and-customizable-modals-with-react-and-typescript-4555</guid>
      <description>&lt;p&gt;As a frontend developer, you have probably had to build a modal window on more than one occasion. This type of element differs from the typical pop-ups because it does not appear automatically, but it is the user who has to click somewhere on the website (usually a button) to make it appear.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will learn how to develop and implement a modal component in your React project with TypeScript. It will be reusable in any part of your application, and you will be able to customize it and add any type of content.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Modal Windows?
&lt;/h2&gt;

&lt;p&gt;Modals are undoubtedly one of the most used components on the web because they can be used in different contexts, from messages to user input. They have placed an overlay on the screen. Therefore, they have visual precedence over all other elements.&lt;/p&gt;

&lt;p&gt;Like many other components in React, a dependency can be installed to help in this process. However, we always end up limited in several aspects, and one of them is styling.&lt;/p&gt;

&lt;p&gt;We can create a modal inside or outside the element we call it from in the DOM hierarchy, but to fulfill the definition of a modal, it should be at the same level as the element used as root in React, and to achieve this, we will use the Portals.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Portals in React?
&lt;/h2&gt;

&lt;p&gt;Portals provide a quick and easy way to render children to a DOM node that exists outside the DOM hierarchy of the parent component.&lt;/p&gt;

&lt;p&gt;In React, the default behavior is to render the entire application under a single DOM node — the root of the application, but what if we want to render children outside the root DOM node? And you want children to appear visually on top of its container.&lt;/p&gt;

&lt;p&gt;A Portal can be created using &lt;code&gt;ReactDOM.createPortal(child, container)&lt;/code&gt;. Here the child is a React element, fragment, or string, and the container is the DOM location (node) to which the portal should be injected.&lt;/p&gt;

&lt;p&gt;Below is an example of a modal component created using the above API.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Although a Portal is rendered outside the parent DOM element, it behaves similarly to a normal React component within the application. It can access props and the context API.&lt;/p&gt;

&lt;p&gt;This is because the Portals reside within the React Tree hierarchy, and Portals only affect the HTML DOM structure and do not impact the React component tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing Modals in React
&lt;/h2&gt;

&lt;p&gt;Setting up&lt;br&gt;
We create our application with vite with the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn create vite my-modals-app --template react-ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We install the dependencies that we will need in the project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add styled-components @types/styled-components&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that, we create the following structure for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;src/
├── components/
│   ├── layout/
│   │   ├── Header.tsx
│   │   └── styles.tsx
│   ├── modals/
│   │   ├── Buttons.tsx
│   │   ├── Modal.tsx
│   │   ├── PortalModal.tsx
│   │   ├── index.ts
│   └── └── styles.ts
├── hooks/
│   └── useOnClickOutside.tsx
├── styles/
│   ├── modal.css
│   ├── normalize.css
│   └── theme.ts
├── ts/
│   ├── interfaces/
│   │   └── modal.interface.ts
│   ├── types/
│   └── └── styled.d.ts
├── App.tsx
├── main.tsx
└── config-dummy.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;p&gt;As we can see in the folder structure, we have several functional and styling components for this app, but in order not to make this tutorial long, we will focus only on the main components.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.tsx&lt;/code&gt;: In this component, we have examples of how to use our custom modal. We have buttons that show modals with different configurations to give us an idea of what we can achieve with this modal.&lt;/p&gt;

&lt;p&gt;In this component, we also define the theme for our modal, adding a &lt;code&gt;ThemeProvider&lt;/code&gt; and creating a global style with &lt;code&gt;createGlobalStyle&lt;/code&gt; of &lt;code&gt;styled-components&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Modal.tsx&lt;/code&gt;: This component is conditioned to be displayed or not depending on the action performed by the user. It is wrapped in a style component that is superimposed on the screen.&lt;/p&gt;

&lt;p&gt;This component receives as property the configuration that is where we will define how our modal will be seen, that is to say, the position where it will be shown, the title of the modal, paddings, etc.&lt;/p&gt;

&lt;p&gt;It also receives children, which contains all the content that will be shown inside the modal. It can be any type of &lt;code&gt;tsx&lt;/code&gt; content.&lt;/p&gt;

&lt;p&gt;Also, in this component, we have a couple of functionalities, which serve us to close the modal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useOnClickOutside&lt;/code&gt;: This is a custom hook that will close the modal when it detects that the user clicks outside the modal.&lt;/p&gt;

&lt;p&gt;This hook receives as a parameter the reference of the element that we want to detect and a callback that is the action that we want to make when detecting a click.&lt;/p&gt;

&lt;p&gt;This hook adds an &lt;code&gt;EventListener&lt;/code&gt; that will respond to the &lt;code&gt;mousedown&lt;/code&gt; and touchstartevent, after this, it will evaluate if the click was inside the element or outside of it.&lt;/p&gt;

&lt;p&gt;handleKeyPress: This is a callback that will be executed when it detects that the user presses the ESC key to close the modal.&lt;/p&gt;

&lt;p&gt;It does this by adding an &lt;code&gt;EventListener&lt;/code&gt; to the &lt;code&gt;keydownevent&lt;/code&gt; to then evaluate which key was pressed.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;PortalModal.tsx&lt;/code&gt;: This component uses the React Portals, which we have already mentioned previously.&lt;/p&gt;

&lt;p&gt;It receives children that would be our modal and an id that we will use to assign it to an HTML element.&lt;/p&gt;

&lt;p&gt;In this component, we use the hook &lt;code&gt;useLayoutEffect&lt;/code&gt;. This hook is a little different from useEffect since this one is executed when it detects a change in the virtual DOM and not in the state, which is exactly what we are doing when creating a new element in the DOM.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;useLayoutEffect&lt;/code&gt;, we look for and validate if the element has already been created with the id that we have passed, and we set this element. Otherwise, we make a new element in the DOM with the function &lt;code&gt;createWrapperAndAppenToBody&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this function, we can create the element where it best suits us. In this case, it is being created at the same level as the root element within the body.&lt;/p&gt;

&lt;p&gt;Once we have created the element where we are going to insert our modal, we create the portal with &lt;code&gt;createPortal&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;configDummy.ts&lt;/code&gt;: This is the file we will use as a template to generate different modals, in this case, 4.&lt;/p&gt;

&lt;p&gt;As you can see, you can make a lot of combinations to generate a modal different from each other, and you could add more configurations if you wish.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That’s it! we have our cool Modals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://resusable-customizable-modals.netlify.app/"&gt;See the demo here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ljaviertovar/reusable-modals-react-ts"&gt;Repo here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have created a reusable component as we can use it anywhere in our application. Using React Portals, we can insert it anywhere in the DOM as it will create a new element with the id, we assign to it.&lt;/p&gt;

&lt;p&gt;We also have different styling options for our modal, and we can add the ones we can think of, besides having implemented a dark mode that I particularly like.&lt;/p&gt;

&lt;p&gt;I hope this tutorial has been useful for you and that you have learned new things in developing this application.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/autocomplete-search-component-with-react-and-typescript-2lj3"&gt;How to build an autocomplete search component in React and TypeScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/why-should-you-use-cleanup-functions-in-reacts-useeffect-hook-2g2c"&gt;Why Should You Use Cleanup Functions in React’s useEffect Hook?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to Connect?&lt;br&gt;
Love connecting with friends all around the world on &lt;a href="https://twitter.com/ljaviertovar"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Improve User Experience with a Modern Skeleton Loader in React</title>
      <dc:creator>L Javier Tovar</dc:creator>
      <pubDate>Sat, 26 Nov 2022 04:43:34 +0000</pubDate>
      <link>https://forem.com/ljaviertovar/how-to-build-a-skeleton-loader-with-react-3k9o</link>
      <guid>https://forem.com/ljaviertovar/how-to-build-a-skeleton-loader-with-react-3k9o</guid>
      <description>&lt;h2&gt;
  
  
  Create a Skeleton UI with React Loading Skeleton
&lt;/h2&gt;

&lt;p&gt;We have all experienced that moment when we don’t know if the website we are accessing is doing something in the background or if it has simply crashed and left us waiting for a response.&lt;/p&gt;

&lt;p&gt;That uncertainty of not knowing what is happening causes a terrible user experience, which today, we must pay close attention to as web developers.&lt;/p&gt;

&lt;p&gt;Whenever we make a request to our back-end or some other external service, there is a time in which our application waits to receive the requested information. It is at this point that we must inform the user that something is happening.&lt;/p&gt;

&lt;p&gt;To solve this problem, we will use Skeleton Loaders, which are a modern form of what have been the traditional Spinners and Loaders. Spinners and Loaders fulfill their function of informing users that content will take time to load, but for modern web development, they are becoming obsolete.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Skeleton Loaders?
&lt;/h2&gt;

&lt;p&gt;A loading skeleton is a version of the user interface that does not include the actual content but instead mimics the page layout by displaying its elements similar to the actual content as it loads and becomes available.&lt;/p&gt;

&lt;p&gt;A skeleton display is essentially a wireframe structure of the page, with placeholder boxes for text and images.&lt;/p&gt;

&lt;p&gt;A skeleton UI resembles the actual UI of the page, so users will understand how quickly the web or mobile application will load even before the content is displayed.&lt;/p&gt;

&lt;p&gt;Here are a couple of reasons why you might want to consider using skeleton screens in your next project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mimicking a page layout is easier with a skeleton screen,&lt;/li&gt;
&lt;li&gt;Content loads progressively (not all at once).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skeleton Loading is also known as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;skeleton screens&lt;/li&gt;
&lt;li&gt;ghost elements&lt;/li&gt;
&lt;li&gt;content placeholders&lt;/li&gt;
&lt;li&gt;content loaders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0r862khk8fexi8vr2jfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0r862khk8fexi8vr2jfy.png" alt="skeleton image example" width="700" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are different types of skeleton Screens and libraries that help us to implement them. In this tutorial, we will work with &lt;a href="https://www.npmjs.com/package/react-loading-skeleton" rel="noopener noreferrer"&gt;React Loading Skeleton&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Skeleton Loading
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It is API-based, and it has one component with props for all customization.&lt;/li&gt;
&lt;li&gt;It can be used as a separate skeleton component and also inside any component directly, so it’s flexible.&lt;/li&gt;
&lt;li&gt;It supports theming and Pulse animation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It’s easy to implement for a simple Skeleton UI but complicated for more complex skeletons.&lt;/li&gt;
&lt;li&gt;Having a separate skeleton component will make it harder to maintain when the UI and styles change.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building a Skeleton Loader for an eCommerce Product Gallery page
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will create a product gallery explaining the main properties offered by the library.&lt;/p&gt;

&lt;p&gt;Here is what we will develop:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51rccdoxy307xczxf305.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51rccdoxy307xczxf305.gif" alt="Before Skeleton Loading" width="700" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndra94za1ro6a96u70t8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndra94za1ro6a96u70t8.gif" alt="After Skeleton Loading" width="700" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start by creating a new project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing is to install the libraries we will use. In this case, we will use &lt;code&gt;styled-components&lt;/code&gt; for the styles, &lt;code&gt;react-icons&lt;/code&gt; for the icons, &lt;code&gt;axios&lt;/code&gt; for the data fetching, and of course, &lt;code&gt;react-loading-skeleton&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;react-loading-skeleton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we create the following structure for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jpg&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;Banner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;Gallery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;Plp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it is a very simple project where the only components that interest us are Banner.js and Gallery.js, where we have implemented the Skeleton Loading.&lt;/p&gt;

&lt;p&gt;The rest of the components are just to shape the project and simulate an e-commerce product page. I will leave the repository at the end of the post.&lt;/p&gt;

&lt;p&gt;Now let’s start explaining what interests us about the project. First, we are going to add some dummy products to show them in our gallery. For this, we will use &lt;a href="https://fakestoreapi.com/" rel="noopener noreferrer"&gt;fakeStoreAPI&lt;/a&gt;, which is a free online REST API that you can use whenever you need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://fakestoreapi.com/products/category/electronics/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                
  &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;               
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this endpoint, what we get is a JSON with dummy products from the electronics category and, we get a response like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WD 2TB Elements Portable External Hard Drive - USB 3.0 "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USB 3.0 and USB 2.0 ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://fakestoreapi.com/img/61IBBVJvSDL._AC_SY879_.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;203&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SanDisk SSD PLUS 1TB Internal SSD - SATA III 6 Gb/s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;109&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Easy upgrade for ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"electronics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://fakestoreapi.com/img/61U7T1koQqL._AC_SX679_.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;470&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to misuse the data received from the API and create a product card for each item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GalleryStyles&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;            
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gallery__title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Featured&lt;/span&gt; &lt;span class="nx"&gt;Products&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gallery__grid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;                    
      &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                        
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;                            
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-rating&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FaStar&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item__btns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item__btnadd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item__btnbuy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="nx"&gt;Buy&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;                               &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/article&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;                    
      &lt;span class="p"&gt;})&lt;/span&gt;                
    &lt;span class="p"&gt;}&lt;/span&gt;            
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;       &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/GalleryStyles&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our gallery created, we move on to create the Skeleton Loading of each product card.&lt;/p&gt;

&lt;p&gt;The first thing to do is import the library and the CSS styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Skeleton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SkeletonTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-loading-skeleton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-loading-skeleton/dist/skeleton.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we saw previously, the Skeleton Loading is mainly based on making a layout as close as possible to the component we want to represent. So, we will copy as such the structure of the component that is inside the &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; tag which is the product card we want to represent.&lt;/p&gt;

&lt;p&gt;To keep the structure as similar as possible, we will try to respect all the HTML tags that we have used to layout the component as well as the classes. The magic of the Skeleton Loading consists of replacing the content of each element with its component &lt;code&gt;&amp;lt;Skeleton/&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item-info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Skeleton&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skeleton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/article&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we can leave the default &lt;code&gt;&amp;lt;Skeleton/&amp;gt;&lt;/code&gt; component without modifying any properties, it works correctly but we might notice that our Skeleton doesn’t look much like our final component, so we will use some of its properties to make it more similar.&lt;/p&gt;

&lt;p&gt;Skeleton react loading provides us with several properties to style our Skeleton.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; we add the width and height of the Skeleton in px.&lt;/li&gt;
&lt;li&gt;With a &lt;code&gt;circle&lt;/code&gt; we make a Skeleton a circular figure and this property is a boolean.&lt;/li&gt;
&lt;li&gt;We also have a &lt;code&gt;count&lt;/code&gt; which replicates n quantity of Skeletons or rows of Skeletons as we indicate it.&lt;/li&gt;
&lt;li&gt;In the same way, we can change the speed of the animation that brings us by default that is 0.2, and we do it with the &lt;code&gt;duration&lt;/code&gt; property.&lt;/li&gt;
&lt;li&gt;In addition, the library offers us the option to change the colors of the Skeleton, we do it with its &lt;code&gt;&amp;lt;SkeletonTheme&amp;gt;&lt;/code&gt; component where we can change the base color and the color of the animation.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SkeletonTheme&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#F5F5F5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;highlightColor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SkeletonTheme&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are more properties but in this tutorial, We only use the most used ones. Now we can see that our Skeleton already looks much more like our product sheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lp339u3ntmrhbpi3m9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lp339u3ntmrhbpi3m9f.png" alt="Skeleton example" width="700" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we have the problem that We don’t know how many elements the fetching will return to us at the data we use. Therefore, we do not know how many Skeletons we should paint.&lt;/p&gt;

&lt;p&gt;That is solved if we have defined pagination in the gallery, then we already know that for each page, We will show n amount of elements.&lt;/p&gt;

&lt;p&gt;If we do not have any pagination implemented, what we could do, is to define a specific number of skeletons we want to display or check how many elements are visible in the viewport to display the necessary skeletons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skeleton-loading-ecommerce.netlify.app/" rel="noopener noreferrer"&gt;See the demo here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ljaviertovar/react-skeleton-ecommerce" rel="noopener noreferrer"&gt;Repo here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we can see, it is not difficult to create Skeletons Loadings for our websites and add a great user experience.&lt;/p&gt;

&lt;p&gt;However, there are points to consider when implementing Skeletons, for example, if we need a fast development, it is not a good idea to use them because they add another layer of logic to our components, besides if we are still in the development of the components these can change several times and, we will have to do the same with our Skeletons every time we modify the design of our component.&lt;/p&gt;

&lt;p&gt;My recommendation would be to implement Skeleton Loading at the end of our project, when we have the final design of each component, or keep a simple Skeleton representing only the component container and at the end of the development give the final structure of our design to the Skeleton.&lt;/p&gt;

&lt;p&gt;Undoubtedly, they are an excellent alternative to avoid seeing blank screens.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/take-your-modals-to-the-next-level-how-to-create-reusable-and-customizable-modals-with-react-and-typescript-4555"&gt;How to create reusable and customizable modals with React and TypeScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/how-to-hide-your-api-keys-and-tokens-in-react-to-protect-your-application-1dmc"&gt;How to hide your API keys and tokens in React to protect your application&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to Connect?&lt;br&gt;
Love connecting with friends all around the world on &lt;a href="https://twitter.com/ljaviertovar" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>devto</category>
    </item>
    <item>
      <title>Why Should You Use Cleanup Functions in React’s useEffect Hook?</title>
      <dc:creator>L Javier Tovar</dc:creator>
      <pubDate>Wed, 09 Nov 2022 03:17:22 +0000</pubDate>
      <link>https://forem.com/ljaviertovar/why-should-you-use-cleanup-functions-in-reacts-useeffect-hook-2g2c</link>
      <guid>https://forem.com/ljaviertovar/why-should-you-use-cleanup-functions-in-reacts-useeffect-hook-2g2c</guid>
      <description>&lt;h2&gt;
  
  
  Cleanup functions in React’s useEffect hook — explained with examples.
&lt;/h2&gt;

&lt;p&gt;f you are starting to learn React or already have some time using this library, surely, you have come across some errors or warnings related to asynchronous functions, especially using the hook &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When I was learning the functionality of this hook, I could not understand the reason to use the return in this function since in most cases it is not necessary to use it and React works perfectly well without it.&lt;/p&gt;

&lt;p&gt;As I became more familiar with the way React works and the life cycle of the components, I began to notice that in many cases, it is too important to use the return in the hook &lt;code&gt;useEffect&lt;/code&gt;, especially in the side effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the side effects?
&lt;/h2&gt;

&lt;p&gt;A side effect can be fetching data from a remote server, reading or writing to local storage, setting up event listeners, or setting up a subscription. These side effects can occur when a button is clicked, when a form is submitted, or when a component is mounted and unmounted.&lt;/p&gt;

&lt;p&gt;React’s &lt;a href="https://reactjs.org/docs/hooks-reference.html#useeffect"&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; hook allows functional components to do things when a component is mounted or when some properties or states change. This hook also allows to clean up when the component is unmounted.&lt;/p&gt;

&lt;p&gt;Why clean up side effects?&lt;br&gt;
Handling side effects in React is a task of medium complexity. However, from time to time, you may have difficulties at the intersection of the component lifecycle (initial rendering, assembly, usage, disassembly) and the side-effect lifecycle (started, in progress, complete).&lt;/p&gt;

&lt;p&gt;One such difficulty is when a side effect completes and attempts to update the state of an already disassembled component.&lt;/p&gt;

&lt;p&gt;This causes a React warning like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qlrvxk1O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8d3mjk5zknziuugvvh89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlrvxk1O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8d3mjk5zknziuugvvh89.png" alt="Error react" width="700" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memory leaks in React applications are mainly the result of not canceling subscriptions made when a component was mounted before the component is unmounted.&lt;/p&gt;

&lt;p&gt;They cause many problems, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Affects the performance of the project by reducing the amount of memory available.&lt;/li&gt;
&lt;li&gt;Slowing down the application.&lt;/li&gt;
&lt;li&gt;System crashes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, it’s necessary to eliminate memory leak problems.&lt;/p&gt;

&lt;p&gt;What is the &lt;code&gt;useEffect&lt;/code&gt; cleanup function?&lt;br&gt;
It is a function of the useEffect hook that allows us to stop side effects that no longer need to be executed before our component is unmounted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is built in such a way that we can return a function inside it and this return function is where the cleanup happens.&lt;/p&gt;

&lt;p&gt;For example, Component A requests the API to get a list of products, but while making that asynchronous request, Component A is removed from the DOM (it’s unmounted). There is no need to complete that asynchronous request.&lt;/p&gt;

&lt;p&gt;So as a cleanup method to improve your application, you can clean up (cancel) the asynchronous request so that it’s not completed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/docs/hooks-effect.html#effects-without-cleanup"&gt;Cleanup function of useEffect&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your effect&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Cleanup&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Cleaning up an effect
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Canceling a fetch request
&lt;/h3&gt;

&lt;p&gt;There are different ways to cancel fetch request calls, we can use fetch &lt;a href="https://javascript.info/fetch-abort#:~:text=To%20be%20able%20to%20cancel,how%20to%20work%20with%20AbortController%20."&gt;AbortControlleror&lt;/a&gt; Axios &lt;a href="https://axios-http.com/docs/cancellation"&gt;AbortController&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To use &lt;code&gt;AbortController&lt;/code&gt;, we must create a controller using the &lt;code&gt;AbortController()&lt;/code&gt; constructor. Then, when our fetch request initiates, we pass &lt;code&gt;AbortSignal&lt;/code&gt; as an option inside the request’s &lt;code&gt;options&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;This associates the controller and signal with the fetch request and lets us cancel it anytime using &lt;code&gt;AbortController.abort()&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Cleaning up Timeouts
&lt;/h2&gt;

&lt;p&gt;When using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/setTimeout"&gt;setTimeout&lt;/a&gt;(callback, time) timer functions, we can clear them on unmount by using the special &lt;code&gt;clearTimeout(timerId)&lt;/code&gt; function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Cleaning up Intervals
&lt;/h2&gt;

&lt;p&gt;Like the Timeouts, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/setInterval"&gt;setIntervals&lt;/a&gt;(callback, time)have a special function to clean them up with &lt;code&gt;clearInterval(intervalId)&lt;/code&gt; function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Cleaning up Event Listeners
&lt;/h2&gt;

&lt;p&gt;Clean up Listeners happens via &lt;a href="https://developer.mozilla.org/es/docs/Web/API/EventTarget/removeEventListener"&gt;window.removeEventListener&lt;/a&gt;. The &lt;code&gt;removeEventListener&lt;/code&gt; call must reference the same function in the &lt;code&gt;removeEventListener&lt;/code&gt;call to remove the listener correctly.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Cleaning up Web Sockets
&lt;/h2&gt;

&lt;p&gt;When you create a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket"&gt;WebSocket&lt;/a&gt; connection, you can close it in the cleanup &lt;code&gt;socket.close()&lt;/code&gt; function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have learned that some side effects require cleanup to avoid memory leaks and unnecessary and unwanted behaviors. We must learn when and how to use the cleanup function of the useEffecthook to avoid these problems and optimize applications.&lt;/p&gt;

&lt;p&gt;I recommend cleaning up asynchronous effects when the component is unmounted. Also, if the asynchronous side effect depends on the prop or state values then consider also cleaning them up when the component is updated.&lt;/p&gt;

&lt;p&gt;I hope you found this article useful and that you can now use the cleanup feature correctly.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/autocomplete-search-component-with-react-and-typescript-2lj3"&gt;How to build an autocomplete search component in React and TypeScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/how-to-hide-your-api-keys-and-tokens-in-react-to-protect-your-application-1dmc"&gt;How to hide your API keys and tokens in React to protect your application&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Want to Connect?&lt;/strong&gt;&lt;br&gt;
Love connecting with friends all around the world on &lt;a href="https://twitter.com/ljaviertovar"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to build an autocomplete search component in React and TypeScript</title>
      <dc:creator>L Javier Tovar</dc:creator>
      <pubDate>Sun, 06 Nov 2022 23:18:50 +0000</pubDate>
      <link>https://forem.com/ljaviertovar/autocomplete-search-component-with-react-and-typescript-2lj3</link>
      <guid>https://forem.com/ljaviertovar/autocomplete-search-component-with-react-and-typescript-2lj3</guid>
      <description>&lt;h2&gt;
  
  
  How to show suggestions of data from an API Rest
&lt;/h2&gt;

&lt;p&gt;Nowadays, one of the most widely used components of a website is the search engines with autocomplete or suggestions.&lt;/p&gt;

&lt;p&gt;It is usually the first component with which the user interacts since it is more practical to perform a search and go directly to what we need. These components are essential in sites such as e-commerce for a good user experience.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a simple search component that offers users suggestions about what they are typing without third-party libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Autocomplete Search?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Autocomplete is a pattern used to display query suggestions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An autocomplete search, also called “predictive search” or “autosuggest,” is a component that the user types in the input field that will suggest various predictions or possible results of how the search might be completed.&lt;/p&gt;

&lt;p&gt;Autocomplete works with a search engine that learns and improves the suggested results as it is fed by the searches its users perform.&lt;/p&gt;

&lt;p&gt;In this case, we will not see more about search engines because it is out of the scope of the tutorial. If you want to learn more about this topic, you can look at this &lt;a href="https://www.addsearch.com/blog/autocomplete-search/"&gt;site&lt;/a&gt;. Without further ado, let’s get to programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Autocomplete search
&lt;/h2&gt;

&lt;p&gt;We create our application with &lt;a href="https://vitejs.dev/guide/#scaffolding-your-first-vite-project"&gt;vite&lt;/a&gt; with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create vite autocomplete-search &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We install the dependencies that we will need in the project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @nextui-org/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this case, I am only going to use a third-party library for the styles you can use whatever you want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextui.org/"&gt;nextui&lt;/a&gt; a Javascript/CSS framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that, we create the following folder structure for the project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── components/
│   └── ui/
│       ├── Autocomplete.tsx
│       ├── Autocomplete.tsx
│       ├── index.ts
│       └── ui.module.css
├── hooks/
│   └── useAutocomplete.ts
├── ts/
│   └──interfaces/
│      └── Country.interface.ts
├── App.tsx
└── main.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;AutocompleteWrapper.tsx&lt;/code&gt; This component is only used as a container or wrapper of &lt;code&gt;Autocomplete.tsx&lt;/code&gt; and is where we are going to request the data we need.&lt;/p&gt;

&lt;p&gt;We use the &lt;a href="https://restcountries.com/"&gt;restcountries&lt;/a&gt; API for the tutorial and only use English-speaking countries so that the query will be as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://restcountries.com/v3.1/lang/eng
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Autocomplete.tsx&lt;/code&gt; This is the main component, and it has two sections. The first section is the input element, and the second is the list of suggestions.&lt;/p&gt;

&lt;p&gt;Usually, a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; element is used, but in this tutorial, we will use Rows components inside a Next UI Card component.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;First, we create the types we need. The API returns us a large amount of data that we will not use, so simplifying the information and the types would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Name&lt;/span&gt;
  &lt;span class="na"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Flags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;png&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After that, we will create the following states:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;searchedValue&lt;/code&gt; — Here, we will store the text user is typing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;suggestions&lt;/code&gt; — Here, we will store the suggestions that match what the user writes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;selectedSuggestion&lt;/code&gt; — Here, we will store the option selected by the user.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;activeSuggestion&lt;/code&gt; — Here, we will store the index of the suggestions shown. We will use it to know which suggestion is selected by the keyboard.&lt;/p&gt;

&lt;p&gt;Now, we need to create the functions that will react to the events of the input element and the results list.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;handleChange()&lt;/code&gt; This function will be executed every time the user types something in the input element. We’ll validate if what is entered isn’t an empty value. Otherwise, we’ll set the states to their initial values.&lt;/p&gt;

&lt;p&gt;If the value received in the input element isn’t empty, the function will be executed and display the suggestions that match the value entered.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;handleClick()&lt;/code&gt; This function will be executed when the user selects a suggestion; we save the selected value and set the remaining states to their initial values.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;handleKeyDown()&lt;/code&gt; This function will be executed when an event is detected on the keyboard, so you can browse through the suggestions and select one.&lt;/p&gt;

&lt;p&gt;Finally, we add a &lt;code&gt;useEffect&lt;/code&gt; to focus on the input element when the component is mounted.&lt;/p&gt;

&lt;p&gt;That’s all! We already have an autocomplete search we can use in any project by passing the input reference and the data to filter.&lt;/p&gt;

&lt;p&gt;As an additional step and good practice, we will take the functionality to a custom hook, and our component will be cleaner and more readable.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The app looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KhWuKGY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scn36vs5nehfmgqum0ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KhWuKGY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scn36vs5nehfmgqum0ga.png" alt="Autocomplete search" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://autocomplete-search-react-ts.vercel.app/"&gt;&lt;strong&gt;See the demo here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ljaviertovar/autocomplete-search-react-ts"&gt;Repo here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have created a simple search component by applying filters to the data received this search could get more and more complicated depending on the case. After capturing the selected value, you could add more functionality, such as displaying the details of the country selected.&lt;/p&gt;

&lt;p&gt;I hope this tutorial has been useful for you and that you have learned new things in developing this application.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/why-should-you-use-cleanup-functions-in-reacts-useeffect-hook-2g2c"&gt;Why Should You Use Cleanup Functions in React’s useEffect Hook?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ljaviertovar/how-to-build-a-skeleton-loader-with-react-3k9o"&gt;Improve User Experience with a Modern Skeleton Loader in React&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Want to Connect?&lt;/strong&gt;&lt;br&gt;
Love connecting with friends all around the world on &lt;a href="https://twitter.com/ljaviertovar"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
