<?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>DEV Community: Paul-Simon Emechebe</title>
    <description>The latest articles on DEV Community by Paul-Simon Emechebe (@paul_emechebe).</description>
    <link>https://dev.to/paul_emechebe</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%2F874557%2F8c93d469-c155-4191-b23a-b2460757e7fe.png</url>
      <title>DEV Community: Paul-Simon Emechebe</title>
      <link>https://dev.to/paul_emechebe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paul_emechebe"/>
    <language>en</language>
    <item>
      <title>Building a startup (build log 2#): Authenticating students with Supabase</title>
      <dc:creator>Paul-Simon Emechebe</dc:creator>
      <pubDate>Thu, 20 Oct 2022 16:37:32 +0000</pubDate>
      <link>https://dev.to/paul_emechebe/building-a-startup-build-log-2-authenticating-users-with-supabase-1p1b</link>
      <guid>https://dev.to/paul_emechebe/building-a-startup-build-log-2-authenticating-users-with-supabase-1p1b</guid>
      <description>&lt;p&gt;I've decided to start documenting my journey as the CTO of Grow. Here is the second build log (build log 2#) where I discuss in detail the development process of how I built the authentication layer for our dashboard.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  What is Grow?
&lt;/h1&gt;

&lt;p&gt;This is a tweet from our CEO at Grow describing what Grow is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oXaSo7b9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ybpycc6pieqdca31cco1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oXaSo7b9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ybpycc6pieqdca31cco1.png" alt="What Grow is" width="631" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this build log, I'll go through the authentication layer for the Grow dashboard. The Grow dashboard is where authenticated users (registered Grow students) have access to course materials, recorded lecture sessions, course agendas, student progress logs, etc. At the time of this publication, the Grow dashboard is still in the infant stages of its development.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccyPdrxv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1581871798332915712/pu/img/FCZExe4pq_pV7wWW.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--txuWWG9q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1511676335458066439/I-gCdGwb_normal.jpg" alt="Paul-Simon Emechebe profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Paul-Simon Emechebe
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ptbthefirst
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Just built a pretty decent form validation with the &lt;a href="https://twitter.com/supabase"&gt;@supabase&lt;/a&gt; database. For someone that has used Firebase all his life, Supabase made Postgres easy. 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      13:00 PM - 17 Oct 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1581993439641468928" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1581993439641468928" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1581993439641468928" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this build log, I'll be covering the following;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The tech stack
&lt;/h3&gt;

&lt;h3&gt;
  
  
  2. The login page UI
&lt;/h3&gt;

&lt;h3&gt;
  
  
  3. The authentication flow
&lt;/h3&gt;

&lt;h3&gt;
  
  
  4. The validation logic
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  The tech stack
&lt;/h1&gt;

&lt;p&gt;The four main dependencies are React, Next.js, Tailwind, and Supabase. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;React.js&lt;/strong&gt;:  I'm using React to build the dashboard. React is an open-source Javascript UI library for building UI components. The concept of React is breaking down your app into independent components that can be completely isolated from the rest of the app when developing, this is possible due to Reacts rendering behavior. Learn more about React.js &lt;a href="https://reactjs.org/"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt;: Next.js is a web framework built on top of React. Amongst a lot of the features it provides, the most notable one is  SSG (server-side rendering). One of the best features Next.js provides is its file-based routing system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind&lt;/strong&gt;: Tailwind is a CSS framework that gives you the ability to inline-style using pre-built utility classes. Learn more about Tailwind &lt;a href="https://tailwindcss.com/"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt;: Supabase is a suite of open-source tools/software to help you build apps using Postgres. The Supabase database is what we used to store all the data for our registered students. They also offer authentication but I didn't see the need to do my user validation on Supabase, I just needed Supabase to give me all our users, then I'd handle the validation logic on the client. 
Why? I'll touch on that in the authentication flow section. Learn more about Supabase &lt;a href="https://supabase.com/"&gt;here&lt;/a&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  The login page UI
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2DAHG_e0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq0knopctboovdrw9crd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2DAHG_e0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq0knopctboovdrw9crd.png" alt="login UI" width="621" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this section, I go through the process of building the UI of the login page i.e styling, folder structure, and component structure.&lt;br&gt;
At the time of this publication, the UI of the login page was not yet built with our custom UI components (e.g &lt;code&gt;Form&lt;/code&gt;, &lt;code&gt;FormInput&lt;/code&gt;, and &lt;code&gt;FormLabel&lt;/code&gt;). So a lot is happening in this single file. No custom hooks, no reusable UI components, and no helper functions. All the logic was done in this single file. This is bad practice for it will catch up with you once you start scaling. Below will show you screenshots of the file. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DISCLAIMER: I am not encouraging this approach to building components. I am just citing an example of what &lt;strong&gt;not to do&lt;/strong&gt;. I built it like this temporarily, just to get something running. Depending on the time you are reading this, the UI must have been written with good scalable practices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Too many &lt;code&gt;Usestate&lt;/code&gt;&lt;/strong&gt;. This is meant to be avoided by dedicating specific state logic to custom hooks.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qHajI1iq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0zd1ugdo9r5xs43q1ef.png" alt="Too many useStates" width="598" height="284"&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redundant styling and HTML&lt;/strong&gt;. This is meant to be avoided by building custom UI components that carry identical styling and possibly logic for the sole purpose of them being reusable. From the picture below. &lt;strong&gt;line 131&lt;/strong&gt; signifies the start and &lt;strong&gt;line 267&lt;/strong&gt; signifies the end. Do the math, that's a total of 136 lines of code for just a login page. That's too many lines of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b9p-co7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhar840xczgv6npdzkq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b9p-co7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhar840xczgv6npdzkq5.png" alt="redundant styling and html" width="409" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication flow
&lt;/h2&gt;

&lt;p&gt;Here I go through the user journey of the login page.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---dS42tUe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fftc393iao12birzovmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---dS42tUe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fftc393iao12birzovmu.png" alt="authentication flow" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;These are the steps that the User undergoes to get authenticated as a student. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Step 1&lt;/strong&gt;: The user does a manual registration in the venue of the Bootcamp and gets an OTP code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 2&lt;/strong&gt;: The user goes to the Grow Dashboard login page. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 3&lt;/strong&gt;: The user logs in with the first name he/she used for the manual registration and the OTP code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Validation logic
&lt;/h1&gt;

&lt;p&gt;In this section, I discuss the logic I wrote to securely validate that the user logging in is indeed who he/she claims ( input ) to be. &lt;br&gt;
First of all, we'll take an overview of what happens behind the scene. Below is a diagram of two parties, the client ( the app ) and the database/server ( Supabase ). Supabase provides a feature called &lt;a href="https://supabase.com/docs/guides/auth"&gt;Supabase Auth&lt;/a&gt; that deals with authenticating users. I didn't use Supabase Auth to authenticate my users, why?&lt;br&gt;
 Due to the fact we are a young startup, we are targeting our students locally. So there was no need of integrating an online payment gateway so we did our payments in person. The in-person payment also requires the student to fill out a form citing the student's credentials. Once the student has done this, the student is officially registered. After this manual registration, the student will be sent an OTP to his/her email to verify his/her account and access his/her dashboard.&lt;/p&gt;

&lt;p&gt;The user data for authentication were&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Students registered full name&lt;/strong&gt;: The full name the student used for manual registration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OTP code&lt;/strong&gt;: The code is sent to the student's email after manual registration has been completed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7FOK6Gzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfu7vlniqk88qjhv7fuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7FOK6Gzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfu7vlniqk88qjhv7fuy.png" alt="login UI" width="621" height="555"&gt;&lt;/a&gt;&lt;br&gt;
Now for the validation logic.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: In the next build log ( build log #3 ), I'm going to discuss the validation logic in detail (line by line). The explanation below is just skimming through the important stuff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PZ-uahnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhxboy9iph9fz27zfaac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PZ-uahnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhxboy9iph9fz27zfaac.png" alt="validation logic diagram" width="880" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above, Supabase doesn't handle the validation logic, all it does is provide all the credentials of manually registered students.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;So what's happening on the client side?&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Di5X9ShT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlg5rvsk0xukwc4lj3lf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Di5X9ShT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlg5rvsk0xukwc4lj3lf.png" alt="validation logic functions" width="733" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I have&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;two functions handling the validation logic ( &lt;code&gt;readSupabse&lt;/code&gt;, &lt;code&gt;onAuthenticate&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;one useEffect&lt;/li&gt;
&lt;li&gt;two components (&lt;code&gt;FullnameValidatoinIcon&lt;/code&gt;, &lt;code&gt;OtpValidationIcon&lt;/code&gt;)
&lt;p&gt; &lt;/p&gt;
Let's briefly describe what they do;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;readSupabase&lt;/code&gt;: &lt;br&gt;
This function contains a Supabase API that does two things;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;reads a list of all the students registered on the database with their various credentials bound to each student. &lt;/li&gt;
&lt;li&gt;filters the list and spits out all the student's full name and OTP codes only
after this API call is run, the filtered data is compared with the user's input. The comparison returns a boolean. so validation is done anytime the user triggers an &lt;code&gt;onChange&lt;/code&gt; on the input field. More on this will be discussed in the next build log (build log 3#).
&lt;p&gt; &lt;/p&gt;
The logic from the &lt;code&gt;readSupabase&lt;/code&gt; function starts checking wether the user is valid or not once the user starts typing&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;below is the validating state&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BRPuwHUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1hai52g1for7z7le6ixi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BRPuwHUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1hai52g1for7z7le6ixi.png" alt="validating state" width="412" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;below is when the validation is false&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PcOewHYQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu6fukpmfu2prbpaofae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PcOewHYQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu6fukpmfu2prbpaofae.png" alt="validation is false" width="417" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;below is when the validation is true&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--raALTmkq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a5o9j2h82gqd0790yar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--raALTmkq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a5o9j2h82gqd0790yar.png" alt="validation is true" width="405" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;onAuthenticate&lt;/code&gt;: &lt;br&gt;
This runs once the user clicks the login button. This function does several things;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;starts the loading state&lt;/li&gt;
&lt;li&gt;checks whether the full name exists in the database&lt;/li&gt;
&lt;li&gt;checks whether the OTP exists in the database&lt;/li&gt;
&lt;li&gt;checks whether the full name and OTP are bound to the same student&lt;/li&gt;
&lt;li&gt;starts a modal state &lt;/li&gt;
&lt;li&gt;redirects to the dashboard
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: in the next build log, I'll go through these line by line&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;FullnameValidationIcon&lt;/code&gt;, and &lt;code&gt;OtpValidationIcon&lt;/code&gt;: &lt;br&gt;
These two components handle the icons on the right of the input fields. They are responsible for displaying the;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;error icon: signifying that the user's input &lt;strong&gt;does not match&lt;/strong&gt; what is in the database&lt;/li&gt;
&lt;li&gt;check icon: signifying that the user's input &lt;strong&gt;matches&lt;/strong&gt; what's on the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;As of the time of writing this, no refactoring was done whatsoever. It's the first iteration of the login page. I just wanted to get things running, in future build logs, I'll discuss how I refactored the login page. Thanks for reading, if you have any suggestions, criticism, or even ways to make these build logs add more value to you guys, feel free to let me know in the comment section below. Have a good day!&lt;/p&gt;

</description>
      <category>startup</category>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>supabase</category>
    </item>
    <item>
      <title>Building a startup (build log 1#): The landing page</title>
      <dc:creator>Paul-Simon Emechebe</dc:creator>
      <pubDate>Fri, 14 Oct 2022 11:00:35 +0000</pubDate>
      <link>https://dev.to/paul_emechebe/building-grow-10-build-log-1-the-landing-page-484d</link>
      <guid>https://dev.to/paul_emechebe/building-grow-10-build-log-1-the-landing-page-484d</guid>
      <description>&lt;p&gt;I've decided to start documenting my journey as the CTO of Grow. Here is the first build log (build log 1#) where I discuss in detail the development process of our landing page.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  What is Grow?
&lt;/h1&gt;

&lt;p&gt;This is a tweet from our CEO at Grow describing what Grow is.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4dMLtcxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2scdy12qqmeaktltrf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4dMLtcxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2scdy12qqmeaktltrf1.png" alt="Our CEO answers it perfectly!!!" width="631" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this build log we'll talk about the decisions I made, the tech stack I used and the obstacles I faced when building the landing page of Grow. But to make this article more orderly. I'll list them into categories.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tech stack:&lt;/strong&gt; the technologies and dependencies used in this project and the particular roles they played.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File structure:&lt;/strong&gt; how I arranged my folders and files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Messiest Bug:&lt;/strong&gt; the bug that took the longest to fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineering corner:&lt;/strong&gt; for my software engineering nerds, in this category I talk about any best practice or framework-specific design pattern i applied in this build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Something new:&lt;/strong&gt; here I'll talk about something new I learned or used when building this project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don'ts:&lt;/strong&gt; here I'll talk about the things I didn't like I did when building. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Lighthouse scores ;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Tech stack
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js:&lt;/strong&gt; Next.js is a React framework with great DX, the main one being SSG. I decided to use Next.js because of;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;its routing system. (I'm not a fan of react-router, routing should be abstracted to a decent point where I don't have to worry about it, and Next.js has helped with that immensely)&lt;/li&gt;
&lt;li&gt;its built-in components e.g the &lt;code&gt;Link&lt;/code&gt; tag helps me transition to different routes on the client and the &lt;code&gt;Image&lt;/code&gt; tag with built-in performance optimization which is very convenient. In particular, the &lt;code&gt;priority&lt;/code&gt; prop optimized the LCP of my home page which was the hero image.&lt;/li&gt;
&lt;li&gt;and other mini perks like its smooth integration with Vercel.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;However, using a JavaScript heavy framework for a landing page is pretty overkill. Although, Next.js tries its best to get you a very optimized build ( e.g per-router code-splitting ), we are still dealing with JavaScript. I would've taken the Svelte route, but as of that time, I had no prior knowledge of Svelte. And we needed to get a landing page up and running fast. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind:&lt;/strong&gt; Tailwind is a CSS framework that gives me the convenience of inline-styling my components with predefined utility classes. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nextauth:&lt;/strong&gt; Nextauth is a library that provides an authentication layer for your Next.js apps. I created a dashboard behind the website so I used Nextauth's Google provider to authenticate users (using their Gmail) that have registered to get access to the dashboard. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;SPOILER ALERT: We decided to build the dashboard in another project entirely so the authentication was not needed. But I still left the integration ( I have instincts ), and just commented on the initiation of the authentication flow ( which is just a line of code. Amazing! )&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chakra UI:&lt;/strong&gt; This is a React UI library that equips you with accessible,modular and reusable UI components. I used Chakra UI only for the registration forms UI, I could've built the UI from scratch, but we needed the site done urgently at that time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase/Firestore:&lt;/strong&gt; Firebase for hosting and Firestore for storing registered user data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framer Motion:&lt;/strong&gt; This is a React animation library. Partially a fan. I don't like how much code I have to write just for a simple text fade-in. But I blame the nature of React. It's pretty hard to abstract animating a react component because of Reacts rendering behavior.
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Folder Structure
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;As cliche as it may sound, I take folder structure very seriously. I always try my best to improve my folder structure game by checking out similar projects on Github, however, this is a landing page so its folder structure would be very simple.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KSxBg85J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbmp6xhsy38tkawhj3wf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KSxBg85J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbmp6xhsy38tkawhj3wf.png" alt="My folder structure" width="372" height="329"&gt;&lt;/a&gt;&lt;br&gt;
let's break them down briefly and go by them one by one&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;components&lt;/code&gt;&lt;/strong&gt;  this is where I put all my components. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JflB9OLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sgdczzdaueddk352lbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JflB9OLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sgdczzdaueddk352lbg.png" alt="The  raw `component` endraw  folder" width="301" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I categorized the components into the two pages that had the most going on. Which was;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The home page&lt;/li&gt;
&lt;li&gt;The registration form page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And yes, I had other pages. But they didn't have components that needed unique layouts or styling. So in building those other pages ( e.g the pricing page ), I reused the components used in the landing page. I tweaked the styling a little and changed the content.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;hooks&lt;/code&gt;&lt;/strong&gt;  this is where I keep all my custom hooks. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UqOWi66l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wl8m69xsq0rf1f5iwkgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UqOWi66l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wl8m69xsq0rf1f5iwkgv.png" alt="the  raw `hooks` endraw  folder" width="271" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;let's go into each of them and see what they do. BRIEFLY.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  useFetchStudentProgress hook
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dZ9W5Z-O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4f63eq8uxtu37wh2rhh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dZ9W5Z-O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4f63eq8uxtu37wh2rhh.png" alt="the  raw `useFetchStudentProgress` endraw  file" width="579" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this hook allows me to fetch data on how far a student has completed his/her course. &lt;br&gt;
Let's now go through it line by line&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;line 1:&lt;/strong&gt; I import the type used for the &lt;code&gt;setDoc&lt;/code&gt; method of Firestore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;line 2:&lt;/strong&gt; I import the &lt;code&gt;fireStore&lt;/code&gt; function I created in the &lt;code&gt;API&lt;/code&gt; folder that abstracts the API methods from firebase for me to use across the app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;line 7:&lt;/strong&gt; inside the &lt;code&gt;useFetchStudentProgress&lt;/code&gt; function i declare a state variable by calling useState, calling the variable studentProgress and the setter setStudentProgress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;line 8:&lt;/strong&gt; inside the &lt;code&gt;initFetchStudentProgress&lt;/code&gt; function, student data is fetched from firestore using the &lt;code&gt;fireStore&lt;/code&gt; api i created. Then updates &lt;code&gt;studentProgress&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;line 13:&lt;/strong&gt; the &lt;code&gt;useFetchStudentProgress&lt;/code&gt; function exposes the fetch function &lt;code&gt;initFetchStudentProgress&lt;/code&gt; and also the state variable of that student data
&lt;p&gt; &lt;/p&gt;
Now for the second custom hook 
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  useScrollPosition
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AwmLsdN1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqabnefokd14vb2h3rd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AwmLsdN1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqabnefokd14vb2h3rd5.png" alt="the  raw `useScrollPosition` endraw  hook" width="637" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This isn't my code. I won't take credit for this. I got this answer from a blog. It returns the number of pixels from the top edge of the document. I used the value of &lt;code&gt;scroll position&lt;/code&gt; on &lt;strong&gt;line 18&lt;/strong&gt; as part of a conditional statement to check whether the user has scrolled or has not scrolled to conditionally add styles to the navigation bar. ( &lt;code&gt;scrollPosition &amp;gt; 0&lt;/code&gt; ) to see the actual code check out the repo &lt;a href="https://github.com/Aisely/Grow/tree/main/src/hooks"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Messiest Bug
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This wasn't necessarily a bug but a performance issue I was manhandling for hours. I deployed my site on two hosting platforms, firebase hosting, and Vercel. Why? 2 reasons&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gideon (my awesome co-founder) wanted the site to be deployed on Firebase hosting because of the default domain Firebase provides ( .web.app ), Vercel's &lt;code&gt;vercel.app&lt;/code&gt; domain name was terrible. Why? we had a problem with migrating our custom domain for the site of another project we worked on before Grow, so we had to remain with the .web.app domain name that firebase provided for that project. The domain registrar we used could not be recognized by Firebase. Check out the project site &lt;a href="https://aisely.web.app/"&gt;here.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;I still wanted to use Vercel because of its wonderful DX and the tools they provide like its deployment log interface.
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now on the bug. I added an animation feature to the site. It was a fade-in animation when in the viewport. I used &lt;a href="https://www.framer.com/docs/use-in-view/"&gt;Framer motion&lt;/a&gt;. So I pushed the changes and pushed them to prod on vercel and firebase. The two sites had an issue.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;on the firebase deployed site:&lt;/strong&gt; All the texts on the home page were not showing. I inspected them and they all rendered. But they were all mysteriously set to hidden.
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;on the vercel deployed site:&lt;/strong&gt; everything was fine and the texts showed. But it took way too long for the texts to render.
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;these are the things I tried but they all didn't work&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;npm installed 400 times and removed npm cache 300 times&lt;/li&gt;
&lt;li&gt;previous deployments on vercel and firebase were working fine, so it had to be a framer motion problem&lt;/li&gt;
&lt;li&gt;reinstalled the package&lt;/li&gt;
&lt;li&gt;suspected a caching problem, so I tried chrome incognito but still nothing.&lt;/li&gt;
&lt;li&gt;Googled the problem, but nothing I saw online was similar to my problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution&lt;/strong&gt;&lt;br&gt;
I saw that the vercel deployed site was showing text but it just took too much time to show the text so I suspected a network issue. So I tried it on another network and found out that the two sites worked perfectly well, rendering and showing the site perfectly. I concluded that my network problem affected framer motion from working well because I later found out that the elements that were integrated with framer motion were the ones affected, not only the text.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Engineering corner
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Presentational and Container Components
&lt;/h3&gt;

&lt;p&gt;This is a pattern in React I use to separate concerns. I find myself using this pattern when I want to separate two things&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What the user sees. (Presentational Component)&lt;/li&gt;
&lt;li&gt;The logic behind it. (Container Component)
This is an oversimplified description of the &lt;strong&gt;Presentational and Container Component&lt;/strong&gt;. If you want to learn more check out Dan Abramov's article &lt;a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0"&gt;here.&lt;/a&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Nlawt1L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eesaehqlq8eh2itaxxdv.png" alt="Presentational and Container component diagram" width="880" height="394"&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Where did I apply this?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: the implementation of this pattern in this use case was pretty low-level. Check out a more thorough guide on how to leverage this pattern in your React apps &lt;a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0"&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the registration form, where interested visitors can register with their credentials and later get feedback from our team, there are three phases to the registration.&lt;br&gt;
&lt;strong&gt;NOTE&lt;/strong&gt;: Chakra UI and a little Tailwind were used to create the UI.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Personal details&lt;/strong&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ulWkrIEL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/904ukm6mc5r09ojoyity.png" alt="personal details phase" width="518" height="511"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contact details&lt;/strong&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--di1WMjVo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0r18me2wwndq5j0uvn7.png" alt="contact details phase" width="473" height="498"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose course&lt;/strong&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UpnxeG9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6791e8u0f3t7xnlym4dv.png" alt="choose course phase" width="501" height="510"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These phases had dedicated components with dedicated files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vFLOl2QX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fhig6hy130mwyloi2du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vFLOl2QX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fhig6hy130mwyloi2du.png" alt="files that contained the phases comoponents" width="249" height="95"&gt;&lt;/a&gt;&lt;br&gt;
In summary, the only logic that was needed for these components was storing the user state and input validations. Those were handled in a single component (Container component) which also contained the &lt;code&gt;ChooseCourse&lt;/code&gt;, &lt;code&gt;ContactDetail&lt;/code&gt;, &lt;code&gt;PersonalDetail&lt;/code&gt; components which each contained the three registration phases respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1yf-kqeA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3yjr41ho03k22amllc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1yf-kqeA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3yjr41ho03k22amllc5.png" alt="wrapper component for the three phases" width="596" height="384"&gt;&lt;/a&gt;&lt;br&gt;
I'll briefly explain the function of those props that are passed down to those components.&lt;br&gt;
&lt;strong&gt;&lt;code&gt;loading&lt;/code&gt;  prop data:&lt;/strong&gt; this handled the loading state for when the user submits the form.&lt;br&gt;
&lt;strong&gt;&lt;code&gt;formData&lt;/code&gt;   prop data:&lt;/strong&gt; This is the state variable which is an object that contained the input values as properties. This was used to persist what the user inputs in the input fields.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k1prsbFc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1pric4a1urh94v1ljro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k1prsbFc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1pric4a1urh94v1ljro.png" alt="example of state persistence in input field" width="609" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FO9tMeNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1gypj8bucchvz1vu7rz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FO9tMeNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1gypj8bucchvz1vu7rz.gif" alt="register flow" width="810" height="538"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;&lt;code&gt;setFormData&lt;/code&gt;  prop data:&lt;/strong&gt; This is the setter function for the &lt;code&gt;formData&lt;/code&gt; state object. Use to update the state object.&lt;br&gt;
&lt;strong&gt;&lt;code&gt;handleSliderChangeBtn&lt;/code&gt;  prop data:&lt;/strong&gt; this is a function that handles the tab transitions by clicking the buttons.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Like I said before, this was just a low-level implementation of this pattern. So if you want to learn more on how you can leverage this pattern check out this article written by a core team member of React, Dan Abramov &lt;a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0"&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Something new!
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Formspark
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://formspark.io/for/react/"&gt;Formspark&lt;/a&gt; provides me with a backend and an API for form submissions. It has a React plugin that is very intuitive. I used it for my form submissions. It was actually a replacement for a similar product called &lt;a href="https://formspree.io/"&gt;Formspree&lt;/a&gt;, but their React integration was way too rigid when it came to customizing behaviors in my form submission flow. &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Dont's
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Overiding Chakra UI
&lt;/h3&gt;

&lt;p&gt;This was my first time using Chakra UI, so I wasn't too familiar with what it could do and I didn't have enough time to really check out the docs because I had to ship this quick. So when I came across certain in-built styles or behaviors Chakra-UI presented that I didn't want, I would override them with custom styles using Tailwind. It got the job done, but it was really messy. As of the time the article was published got my hands a bit dirty in the library, and even made some contributions to docs correction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qs0EEcjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36x7w1pbqo1fokzaniqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qs0EEcjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36x7w1pbqo1fokzaniqv.png" alt="chakra ui PR" width="557" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Not really a fan of Lighthouse because the performance metric highly depends on your network connection. So if you have a shitty network your performance score will drop drastically. But the other metrics are independent of the network connection. When it comes to a proper performance score you can measure, it'll be your bundle sizes.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6CpIqYN---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/412fz7gtqeq9e3m0usoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6CpIqYN---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/412fz7gtqeq9e3m0usoc.png" alt="Lighthouse score" width="464" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7q2a_t3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msm52qpe7vzxxtgmzfg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7q2a_t3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msm52qpe7vzxxtgmzfg6.png" alt="Lighthouse performance score" width="490" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This is the first of my build log series. If this build log was beneficial to you in any way, comment how. Thanks for reading.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Here is the link to Grow's landing page. &lt;a href="https://ecolegrow.tech/"&gt;Click here&lt;/a&gt;&lt;br&gt;
If you wanna stay updated on our progress. Here is Grows twitter handle. &lt;a href="https://twitter.com/AiselyHQ"&gt;Here!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>startup</category>
    </item>
    <item>
      <title>Polymorphic Components: Authoring flexible and reusable components.</title>
      <dc:creator>Paul-Simon Emechebe</dc:creator>
      <pubDate>Mon, 29 Aug 2022 04:00:00 +0000</pubDate>
      <link>https://dev.to/paul_emechebe/polymorphic-components-authoring-flexible-and-reusable-components-1efo</link>
      <guid>https://dev.to/paul_emechebe/polymorphic-components-authoring-flexible-and-reusable-components-1efo</guid>
      <description>&lt;p&gt;When building large react projects, building components to accommodate different variants and elements can be really hard, especially when you're trying to find a way to build reusable and flexible ones. &lt;/p&gt;

&lt;p&gt;In this article I'll demonstrate how to use Polymorphic Components. It's a pattern that provides component consumers with flexibility to configure the components behaviors via props.&lt;br&gt;
 &lt;br&gt;
 &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;/strong&gt;: this example is done using Next.js and tailwind. Nevertheless, this demonstration can be used on any other React framework like CRA.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;if you are following using Next.js:&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;npx&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt; &lt;span class="nx"&gt;polymorphic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;tailwindcss&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you are following using CRA&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;npx&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="nx"&gt;polymorphic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="nx"&gt;tailwindcss&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  Configurations and dependencies
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;clsx&lt;/strong&gt;- this is a package we have to install, a utility for constructing className strings conditionally.
&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="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt; &lt;span class="nx"&gt;clsx&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;for more information on clsx &lt;a href="https://www.npmjs.com/package/clsx" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/clsx&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind nesting&lt;/strong&gt; -We are going to enable nested styles in our postcss.config.ts file. follow these directions &lt;a href="https://tailwindcss.com/docs/using-with-preprocessors#nesting" rel="noopener noreferrer"&gt;https://tailwindcss.com/docs/using-with-preprocessors#nesting&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
 &lt;br&gt;
 &lt;br&gt;
We'll build a single Card Component that we'll reuse three times to display three cards. We'll configure the content/behavior of each of the cards via props in parent component which in this case is the &lt;code&gt;Index&lt;/code&gt; component.&lt;/p&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%2Fprlpc0wbg2xttsg6i4dr.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%2Fprlpc0wbg2xttsg6i4dr.png" alt="Image of the final look"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;

&lt;p&gt;src&lt;br&gt;
   |--components&lt;br&gt;
        |--icons&lt;br&gt;
              |--ReactIcon.tsx&lt;br&gt;
              |--SvelteIcon.tsx&lt;br&gt;
              |--VueIcon.tsx&lt;br&gt;
        |--polymorphic&lt;br&gt;
              |--card.type.ts&lt;br&gt;
              |--Card.ts&lt;br&gt;&lt;br&gt;
        |--Card.module.css&lt;br&gt;
  |--Index.tsx&lt;br&gt;
 &lt;br&gt;
 &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;src/components/polymorphic/card.type.ts&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Card&lt;/code&gt; component will support three variants - react , vue and svelte , so let’s create a file with the &lt;code&gt;CardVariant&lt;/code&gt; type.&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;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CardVariant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;src/components/Card.module.css&lt;/strong&gt;&lt;br&gt;
Here we give styles to each variant&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-left&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;relative&lt;/span&gt; &lt;span class="err"&gt;border-l-4;&lt;/span&gt;

  &lt;span class="err"&gt;&amp;amp;.react&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;flex-col&lt;/span&gt; &lt;span class="err"&gt;bg-[#61dafb]&lt;/span&gt; &lt;span class="err"&gt;bg-opacity-30&lt;/span&gt; &lt;span class="err"&gt;p-4&lt;/span&gt; &lt;span class="err"&gt;w-[300px]&lt;/span&gt; &lt;span class="err"&gt;h-[390px]&lt;/span&gt; &lt;span class="err"&gt;border-2;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;flex-col&lt;/span&gt; &lt;span class="err"&gt;bg-[#4dba87]&lt;/span&gt; &lt;span class="err"&gt;bg-opacity-30&lt;/span&gt; &lt;span class="err"&gt;p-4&lt;/span&gt; &lt;span class="err"&gt;w-[300px]&lt;/span&gt; &lt;span class="err"&gt;h-[390px]&lt;/span&gt; &lt;span class="err"&gt;border-2;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.svelte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;flex-col&lt;/span&gt; &lt;span class="err"&gt;bg-[#ff3e00]&lt;/span&gt; &lt;span class="err"&gt;bg-opacity-30&lt;/span&gt; &lt;span class="err"&gt;p-4&lt;/span&gt; &lt;span class="err"&gt;w-[300px]&lt;/span&gt; &lt;span class="err"&gt;h-[390px]&lt;/span&gt; &lt;span class="err"&gt;border-2;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;let's create the icons!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;src/components/icons/ReactIcon&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReactIconProps&lt;/span&gt; &lt;span class="o"&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;ReactIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactIconProps&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;175.7 78 490.6 436.9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&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;g&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="s2"&gt;#61dafb&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;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9v-22.3c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6v-22.3c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zm-101.4 106.7c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24s9.5 15.8 14.4 23.4zm73.9-208.1c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6s22.9-35.6 58.3-50.6c8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zm53.8 142.9c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6z&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;circle&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;420.9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;296.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;45.7&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;/g&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;/svg&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;/&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;ReactIcon&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;src/components/icons/VueIcon&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;VueIconProps&lt;/span&gt; &lt;span class="o"&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;VueIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VueIconProps&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&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="s2"&gt;w-[150px]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;enable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new 0 0 2500 2165.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 2500 2165.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&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;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m1538.7 0-288.7 500-288.7-500h-961.3l1250 2165.1 1250-2165.1z&lt;/span&gt;&lt;span class="dl"&gt;"&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="s2"&gt;#4dba87&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;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m1538.7 0-288.7 500-288.7-500h-461.3l750 1299 750-1299z&lt;/span&gt;&lt;span class="dl"&gt;"&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="s2"&gt;#435466&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;/svg&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;/&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;VueIcon&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;src/components/icons/SvelteIcon&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SvelteIconProps&lt;/span&gt; &lt;span class="o"&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;SvelteIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SvelteIconProps&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-23.04085003 -23.7 545.4320132 647&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&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;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m466.95 79.52c-55.66-79.62-165.6-103.22-245.08-52.6l-139.58 88.93c-9.39 5.9-18.15 12.76-26.12 20.47-7.98 7.71-15.13 16.23-21.34 25.42s-11.45 19-15.64 29.27a160.478 160.478 0 0 0 -9.26 31.87c-1.65 9.15-2.55 18.43-2.67 27.73-.13 9.31.52 18.61 1.93 27.8 1.41 9.2 3.58 18.27 6.48 27.11s6.53 17.42 10.85 25.66a161.68 161.68 0 0 0 -8.22 13.97c-2.51 4.79-4.77 9.71-6.78 14.73s-3.76 10.14-5.25 15.34-2.71 10.47-3.67 15.79a170.365 170.365 0 0 0 1.55 67.48c2.5 11.05 6.09 21.83 10.73 32.17s10.29 20.2 16.89 29.42c55.66 79.62 165.59 103.22 245.07 52.6l139.58-88.56c9.39-5.91 18.13-12.78 26.1-20.5a160.58 160.58 0 0 0 21.33-25.42c6.21-9.18 11.45-18.99 15.64-29.26 4.19-10.26 7.3-20.94 9.29-31.85 1.65-9.15 2.54-18.42 2.66-27.72s-.53-18.6-1.95-27.79c-1.41-9.19-3.58-18.25-6.49-27.09-2.91-8.83-6.54-17.41-10.86-25.65 2.97-4.51 5.72-9.18 8.23-13.97 2.5-4.79 4.77-9.71 6.78-14.73s3.77-10.14 5.27-15.34c1.49-5.19 2.73-10.46 3.7-15.78 1.98-11.16 2.84-22.49 2.58-33.82s-1.65-22.6-4.15-33.66c-2.5-11.05-6.09-21.83-10.73-32.17a170.906 170.906 0 0 0 -16.87-29.42&lt;/span&gt;&lt;span class="dl"&gt;"&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="s2"&gt;#ff3e00&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;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m208.23 527.78a110.876 110.876 0 0 1 -33.49 3.42c-11.27-.58-22.39-2.86-32.97-6.79a111.06 111.06 0 0 1 -29.42-16.35 111.108 111.108 0 0 1 -23.15-24.42c-3.97-5.55-7.37-11.47-10.15-17.69a102.38 102.38 0 0 1 -6.45-19.34c-1.49-6.65-2.33-13.43-2.48-20.24s.38-13.62 1.58-20.33c.19-1.09.41-2.18.65-3.26.23-1.09.49-2.17.77-3.24.27-1.08.57-2.15.89-3.22.31-1.06.65-2.12 1-3.17l2.63-8.03 7.17 5.35c4.11 3 8.35 5.83 12.7 8.47 4.35 2.65 8.81 5.11 13.37 7.37 4.55 2.27 9.21 4.35 13.94 6.22 4.73 1.88 9.54 3.55 14.42 5.02l5.35 1.55-.48 5.35a31.395 31.395 0 0 0 1.12 10.81c.49 1.76 1.14 3.46 1.93 5.1s1.72 3.21 2.78 4.69a33.4 33.4 0 0 0 6.99 7.35c2.68 2.08 5.67 3.74 8.86 4.92s6.53 1.86 9.93 2.03c3.39.18 6.79-.17 10.08-1.03.76-.2 1.5-.43 2.24-.69s1.47-.54 2.18-.86c.72-.31 1.42-.65 2.12-1.02.69-.36 1.36-.75 2.02-1.17l139.37-88.94a28.96 28.96 0 0 0 4.75-3.72c1.45-1.41 2.74-2.96 3.87-4.63s2.07-3.46 2.83-5.33c.75-1.87 1.31-3.81 1.67-5.79.35-2.03.5-4.08.45-6.14-.05-2.05-.31-4.09-.77-6.1-.45-2-1.11-3.95-1.96-5.83-.84-1.87-1.88-3.65-3.08-5.32-1.94-2.79-4.29-5.26-6.98-7.34s-5.68-3.74-8.86-4.92a33.464 33.464 0 0 0 -9.93-2.04c-3.4-.17-6.8.18-10.09 1.03-.75.2-1.5.43-2.24.69s-1.46.54-2.18.85c-.72.32-1.42.66-2.11 1.03-.69.36-1.37.76-2.03 1.18l-53.52 33.98c-2.18 1.38-4.42 2.68-6.7 3.9-2.29 1.21-4.61 2.34-6.98 3.38s-4.78 1.99-7.22 2.84c-2.44.86-4.91 1.62-7.41 2.29-10.91 2.82-22.18 3.96-33.43 3.38s-22.34-2.87-32.9-6.78c-10.56-3.92-20.46-9.43-29.36-16.33s-16.7-15.11-23.13-24.36c-3.95-5.55-7.34-11.48-10.11-17.7-2.78-6.22-4.93-12.7-6.42-19.34-1.49-6.65-2.31-13.43-2.45-20.24-.15-6.8.38-13.61 1.59-20.31a96.419 96.419 0 0 1 14.94-36.86 96.283 96.283 0 0 1 28.57-27.68l139.8-88.93c2.17-1.38 4.39-2.68 6.66-3.9 2.27-1.21 4.59-2.34 6.94-3.38a98.21 98.21 0 0 1 7.18-2.84c2.42-.86 4.88-1.63 7.37-2.3 10.92-2.83 22.21-3.99 33.47-3.42 11.27.58 22.38 2.86 32.96 6.79 10.58 3.92 20.49 9.44 29.41 16.35a111.11 111.11 0 0 1 23.14 24.43c3.96 5.54 7.37 11.46 10.16 17.68s4.95 12.69 6.46 19.34c1.5 6.65 2.34 13.43 2.49 20.24.16 6.81-.36 13.62-1.56 20.33-.21 1.1-.43 2.2-.68 3.29-.24 1.09-.5 2.18-.78 3.26-.27 1.09-.57 2.17-.88 3.24-.31 1.08-.63 2.15-.98 3.21l-2.67 8.03-7.12-5.35c-4.12-3.03-8.37-5.87-12.73-8.54-4.36-2.66-8.84-5.14-13.41-7.43a182.39 182.39 0 0 0 -28.45-11.32l-5.36-1.55.49-5.35c.15-1.83.14-3.67-.03-5.49-.16-1.82-.49-3.63-.97-5.4-.49-1.76-1.12-3.49-1.91-5.14-.78-1.66-1.71-3.24-2.77-4.74a33.153 33.153 0 0 0 -6.99-7.2 32.991 32.991 0 0 0 -8.82-4.8 33.244 33.244 0 0 0 -19.83-.89c-.76.2-1.51.43-2.24.68-.74.26-1.47.55-2.19.86-.71.31-1.42.66-2.11 1.02-.69.37-1.37.76-2.03 1.18l-139.63 88.78c-1.7 1.07-3.29 2.32-4.73 3.72s-2.74 2.95-3.87 4.61a29.724 29.724 0 0 0 -2.83 5.31c-.76 1.87-1.32 3.8-1.68 5.78-.35 2.03-.5 4.09-.45 6.15a31.547 31.547 0 0 0 2.73 11.95 31.84 31.84 0 0 0 3.07 5.34c1.93 2.76 4.27 5.22 6.94 7.28a33.26 33.26 0 0 0 8.79 4.9 33.533 33.533 0 0 0 19.86 1.09c.75-.21 1.5-.44 2.24-.7.73-.26 1.46-.55 2.18-.86a29.2 29.2 0 0 0 2.11-1.02c.69-.36 1.37-.75 2.03-1.17l53.52-33.92c2.19-1.4 4.42-2.72 6.71-3.94 2.28-1.23 4.61-2.36 6.99-3.41a99.39 99.39 0 0 1 7.23-2.84c2.45-.86 4.93-1.62 7.44-2.28 10.92-2.84 22.2-4 33.47-3.44 11.27.57 22.38 2.85 32.96 6.77 10.57 3.92 20.49 9.43 29.4 16.35 8.92 6.91 16.72 15.14 23.15 24.41 3.96 5.55 7.36 11.47 10.15 17.69a102.65 102.65 0 0 1 6.46 19.34c1.5 6.64 2.34 13.42 2.5 20.23.16 6.82-.37 13.63-1.56 20.33a96.419 96.419 0 0 1 -5.55 19.21 95.753 95.753 0 0 1 -9.4 17.65c-3.73 5.54-8.03 10.68-12.83 15.33s-10.07 8.79-15.73 12.35l-139.64 88.93c-2.19 1.39-4.43 2.7-6.71 3.92-2.29 1.22-4.62 2.35-7 3.39-2.37 1.05-4.78 2-7.23 2.86-2.44.86-4.92 1.63-7.42 2.3&lt;/span&gt;&lt;span class="dl"&gt;"&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="s2"&gt;#fff&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;/svg&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;/&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;SvelteIcon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now it's time to create the &lt;code&gt;Card&lt;/code&gt; component&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/components/polymorphic/Card.tsx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;clsx&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;clsx&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;styles&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;../../components/Card.module.css&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;VueIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SvelteIcon&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;../icons&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;CardVariant&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;./card.types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CardProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;showIcon&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CardVariant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;headerText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="nx"&gt;ICONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SvelteIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VueIcon&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="nx"&gt;Card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CardProps&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;props&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;Icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ICONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;show&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="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="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;variant&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="cm"&gt;/* Logo Icon */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showIcon&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="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="s2"&gt;h-1/2 flex justify-center items-center w-[100%]&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;Icon&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="p"&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="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Header text */&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="s2"&gt;py-3 h-1/2 w-[100%]&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;headerText&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="nx"&gt;div&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="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="s2"&gt;text-2xl mb-1&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;headerText&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="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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Body text */&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="o"&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="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="s2"&gt;text-sm&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;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;children&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="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="p"&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="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;Card&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through what is happening in the &lt;code&gt;Card&lt;/code&gt; component&lt;br&gt;
 &lt;br&gt;
We make the Card component to accept props to give us the ability to configure what the Card should render&lt;/p&gt;

&lt;p&gt;• show - indicates if the Card should be rendered&lt;br&gt;
• variant - specifies the styling variant. &lt;br&gt;
• showIcon - indicates whether the alert icon should be displayed. By default it’s set to true .&lt;br&gt;
• headerText - text for the Card header.&lt;br&gt;
• text - main body text for the Card.&lt;br&gt;
• children - any HTML/React elements, components, etc.&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;type&lt;/span&gt; &lt;span class="nx"&gt;CardProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;showIcon&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CardVariant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;headerText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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; &lt;br&gt;
Next, we have the &lt;code&gt;ICONS&lt;/code&gt; variable, which maps variants to appropriate icon components.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ICONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SvelteIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VueIcon&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; &lt;br&gt;
Here we destructure the props. Also we set the &lt;code&gt;showIcon&lt;/code&gt; to true by default.&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Next, we create the &lt;code&gt;Icon&lt;/code&gt; component to render the Icon according the variant prop.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ICONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
The Card component renders &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an icon&lt;/li&gt;
&lt;li&gt;a header text&lt;/li&gt;
&lt;li&gt;the body
&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;show&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="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="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;variant&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="cm"&gt;/* Logo Icon */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showIcon&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="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="s2"&gt;h-1/2 flex justify-center items-center w-[100%]&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;Icon&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="p"&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="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Header text */&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="s2"&gt;py-3 h-1/2 w-[100%]&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;headerText&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="nx"&gt;div&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="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="s2"&gt;text-2xl mb-1&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;headerText&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="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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Body text */&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="o"&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="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="s2"&gt;text-sm&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;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;children&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="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="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TIP: conditionally rendering your elements based on props ( especially when the prop is a user input ) is good for error handling. In the code above i render the element otherwise return null which won't render anything. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let's use the &lt;code&gt;Card&lt;/code&gt; component&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/Index.tsx&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As said earlier, We will have three cards, one for each variant. Last but not least, we need to update the &lt;code&gt;Index&lt;/code&gt; Component.&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;Card&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;./components/polymorphic/Card&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;Home&lt;/span&gt; &lt;span class="o"&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="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;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;flex flex-col justify-center items-center min-w-[900px] mx-auto p-11&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="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;text-3xl&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;Polymorphic&lt;/span&gt; &lt;span class="nx"&gt;Components&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&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="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;text-xs mb-5 mt-3&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;by&lt;/span&gt; &lt;span class="nx"&gt;Paul&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Simon&lt;/span&gt; &lt;span class="nx"&gt;Emechebe&lt;/span&gt;   &lt;span class="na"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;:@&lt;/span&gt;&lt;span class="nd"&gt;ptbthefirst&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&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;p-6 flex flex-row space-x-6&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;Card&lt;/span&gt; 
          &lt;span class="nx"&gt;show&lt;/span&gt;
          &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React is a free and open-source front-end JavaScript library for building user interfaces based on UI components.&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;Card&lt;/span&gt; 
          &lt;span class="nx"&gt;show&lt;/span&gt;
          &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Svelte is a free and open-source front end compiler created by Rich Harris and maintained by the Svelte core team members.&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;Card&lt;/span&gt; 
          &lt;span class="nx"&gt;show&lt;/span&gt;
          &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vue.js is an open-source model–view–viewmodel front end JavaScript framework for building user interfaces and single-page applications.&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="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;Home&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
 &lt;br&gt;
💥💥💥 We just build a working &lt;code&gt;Card&lt;/code&gt; component that can support different variants/elements. What are your thoughts? Can this pattern be applied to large applications? Have you tried something like this? I would love love to hear from you.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>typescript</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Supercharging your React projects with Memoization</title>
      <dc:creator>Paul-Simon Emechebe</dc:creator>
      <pubDate>Mon, 04 Jul 2022 03:10:38 +0000</pubDate>
      <link>https://dev.to/paul_emechebe/supercharging-react-with-memoization-1999</link>
      <guid>https://dev.to/paul_emechebe/supercharging-react-with-memoization-1999</guid>
      <description>&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; are React hooks for memoization. Think of memoization as caching a value so that it does not need to be recalculated. This improves performance. The main difference between &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; is that &lt;code&gt;useCallback&lt;/code&gt; returns a memoized function (which just really means a 'cached function') and &lt;code&gt;useMemo&lt;/code&gt; returns a memoized value. Let's go through these hooks together.&lt;/p&gt;

&lt;p&gt;Let's start with &lt;code&gt;useMemo&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using useMemo
&lt;/h2&gt;

&lt;p&gt;One reason to use &lt;code&gt;useMemo&lt;/code&gt; is to prevent an expensive function from re-rendering unless one of its dependencies update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;In this example, we have an expensive function that runs on every render.&lt;/p&gt;

&lt;p&gt;When changing the count or adding a todo, you will notice a delay in execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
import ReactDOM from "react-dom";

const App = () =&amp;gt; {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = expensiveCalculation(count);

  const increment = () =&amp;gt; {
    setCount((c) =&amp;gt; c + 1);
  };
  const addTodo = () =&amp;gt; {
    setTodos((t) =&amp;gt; [...t, "New Todo"]);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;My Todos&amp;lt;/h2&amp;gt;
        {todos.map((todo, index) =&amp;gt; {
          return &amp;lt;p key={index}&amp;gt;{todo}&amp;lt;/p&amp;gt;;
        })}
        &amp;lt;button onClick={addTodo}&amp;gt;Add Todo&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;div&amp;gt;
        Count: {count}
        &amp;lt;button onClick={increment}&amp;gt;+&amp;lt;/button&amp;gt;
        &amp;lt;h2&amp;gt;Expensive Calculation&amp;lt;/h2&amp;gt;
        {calculation}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

const expensiveCalculation = (num) =&amp;gt; {
  console.log("Calculating...");
  for (let i = 0; i &amp;lt; 1000000000; i++) {
    num += 1;
  }
  return num;
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('root'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;To fix this performance issue, we have to find a way to prevent the rerender of the expensive function. To do this we'll have to memoize the expensive function. This is done by wrapping the expensive function call with &lt;code&gt;useMemo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useMemo&lt;/code&gt; Hook accepts a second parameter to declare dependencies. The expensive function will only run when its dependencies have changed.&lt;/p&gt;

&lt;p&gt;In the following example, the expensive function will only run when count is changed and not when todo's are added.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useMemo } from "react";
import ReactDOM from "react-dom";

const App = () =&amp;gt; {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = useMemo(() =&amp;gt; expensiveCalculation(count), [count]);

  const increment = () =&amp;gt; {
    setCount((c) =&amp;gt; c + 1);
  };
  const addTodo = () =&amp;gt; {
    setTodos((t) =&amp;gt; [...t, "New Todo"]);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;My Todos&amp;lt;/h2&amp;gt;
        {todos.map((todo, index) =&amp;gt; {
          return &amp;lt;p key={index}&amp;gt;{todo}&amp;lt;/p&amp;gt;;
        })}
        &amp;lt;button onClick={addTodo}&amp;gt;Add Todo&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;div&amp;gt;
        Count: {count}
        &amp;lt;button onClick={increment}&amp;gt;+&amp;lt;/button&amp;gt;
        &amp;lt;h2&amp;gt;Expensive Calculation&amp;lt;/h2&amp;gt;
        {calculation}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

const expensiveCalculation = (num) =&amp;gt; {
  console.log("Calculating...");
  for (let i = 0; i &amp;lt; 1000000000; i++) {
    num += 1;
  }
  return num;
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('root'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's look at useCallback!!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using useCallback
&lt;/h2&gt;

&lt;p&gt;The main difference between useMemo and useCallback is that useCallback returns a memoized function (which just really means a 'cached function') and useMemo returns a memoized value.&lt;/p&gt;

&lt;p&gt;( for the code example for &lt;code&gt;useCallback&lt;/code&gt;, we'll use the exact example used for the &lt;code&gt;useMemo&lt;/code&gt; but the expensive function would be in another component called &lt;code&gt;ExpensiveCalc.js&lt;/code&gt;.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { useState } from "react";
import ReactDOM from "react-dom";

const App = () =&amp;gt; {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);

  const increment = () =&amp;gt; {
    setCount((c) =&amp;gt; c + 1);
  };

  const expensiveCalculation = useCallback((num) =&amp;gt; {
  console.log("Calculating...");
  for (let i = 0; i &amp;lt; 1000000000; i++) {
    num += 1;
  }
  return num;
  }, [count]);  

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;My Todos&amp;lt;/h2&amp;gt;
        {todos.map((todo, index) =&amp;gt; {
          return &amp;lt;p key={index}&amp;gt;{todo}&amp;lt;/p&amp;gt;;
        })}
        &amp;lt;button onClick={addTodo}&amp;gt;Add Todo&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;ExpensiveCalc count={count} increment={increment}/&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};




ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('root'));


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ExpensiveCalc.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { memo } from "react";

const ExpensiveCalc = ({ count, increment }) =&amp;gt; {
  console.log("child render");
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h2&amp;gt;Count&amp;lt;/h2&amp;gt;
      Count: {count}
      &amp;lt;button onClick={increment}&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default memo(ExpensiveCalc); //memo will cause React to skip rendering a component if its props have not changed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>cache</category>
    </item>
    <item>
      <title>Is Virtual DOM overhyped?</title>
      <dc:creator>Paul-Simon Emechebe</dc:creator>
      <pubDate>Mon, 13 Jun 2022 02:15:23 +0000</pubDate>
      <link>https://dev.to/paul_emechebe/is-virtual-dom-overhyped-96</link>
      <guid>https://dev.to/paul_emechebe/is-virtual-dom-overhyped-96</guid>
      <description>&lt;h2&gt;
  
  
  Brief Origin of where the hype began
&lt;/h2&gt;

&lt;p&gt;On the 29th of May, 2013, the pain of building interactive UIs on the web stopped, for on that day the open source library React.js was birth. It introduced features like JSX, Components, one-way data binding and more. One of the top features React brought to the table was the virtual DOM which we will get to in more detail later on. It was said to speed up DOM manipulation. In fact, Pete Hunt, a former React team core member, said that the virtual DOM was built to optimize performance. React later on became to be the most popular framework in 2021 by stack overflow, and it lived happily ever after. Well, not really. The creator of the most loved web framework in 2021, Svelte, Rich Harris called the virtual DOM a "Surprisingly resilient meme". At first I thought this was an unpopular opinion but when I started doing my extensive research (stalking senior developers on Reddit) I got to find out that Rich wasn't alone. In this article I'm going to go through why I might join the band wagon.&lt;/p&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%2Fu6gqr8h0eyom7lryiroy.jpg" 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%2Fu6gqr8h0eyom7lryiroy.jpg" alt="Screenshot from [Rethinking Best Practices](https://www.youtube.com/watch?v=x7cQ3mrcKaY) at JSConfEU 2013"&gt;&lt;/a&gt;Screenshot from &lt;a href="https://www.youtube.com/watch?v=x7cQ3mrcKaY" rel="noopener noreferrer"&gt;Rethinking Best Practices&lt;/a&gt; at JSConfEU 2013&lt;/p&gt;

&lt;h2&gt;
  
  
  What is virtual DOM?
&lt;/h2&gt;

&lt;p&gt;A virtual DOM is a lightweight JavaScript representation of the Document Object Model (DOM) used in declarative web frameworks such as React, Vue.js, and Elm. Put in simple terms, the virtual DOM is a JavaScript Object that stores data about how the DOM looks like at that instant. A way you can look at it is too see the DOM as an office, where all the furniture are elements (e.g. the table is the Nav bar, the chairs is the landing section, and the desk is a button). The virtual DOM is the &lt;strong&gt;blueprint&lt;/strong&gt; of the office.&lt;/p&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%2Fwjp709bozwc6383n3038.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%2Fwjp709bozwc6383n3038.png" alt="virtual DOM and DOM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the virtual DOM?
&lt;/h2&gt;

&lt;p&gt;When writing web pages and apps, one of the most common things you'll want to do is manipulate the document structure in some way. The default way of doing this is by DOM manipulation, i.e. using &lt;code&gt;document.setAttribute()&lt;/code&gt; or &lt;code&gt;document.createElement()&lt;/code&gt;. But one big problem with this was that once a change was made to the DOM the whole document would update. For example, you are building a company website and you need a form for clients to reach out to you, your form is there but you forget to put an input, so you update the form by putting an input tag inside of it. What happens behind the scene is that not only is the form updated but all the html elements(nodes) in the document, yup, all of it. You can imagine if you were building an e-commerce store with 10,000 items represented each in a div tag. That will be a very slow website. So this is where the virtual DOM comes in. The virtual DOM makes it possible for the DOM to only update what has only been changed. How does virtual DOM do it? well, there is this thing called diffing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Diffing
&lt;/h1&gt;

&lt;p&gt;Whenever there is a change in the state of your company website, a new virtual DOM is created. Then the new virtual DOM and the previous virtual DOM are compared with each other. This comparing is called DOM diffing. &lt;/p&gt;

&lt;p&gt;The intention is to perform minimal operations on the real DOM, hence after diffing, the best way to update the real DOM is calculated, leading to an efficient update of your company website.&lt;/p&gt;

&lt;p&gt;The following image shows the diffing process:&lt;/p&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%2Fz4g72q5kyr8gcnagw6ql.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%2Fz4g72q5kyr8gcnagw6ql.png" alt="DOM Diffing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why isn't the creator of Svelte buying into it?
&lt;/h1&gt;

&lt;p&gt;As awesome as it may sound, virtual DOM does posses some bottle necks. let's go through them;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Developer's time is lost:&lt;/strong&gt; Even though extreme levels of performance aren't one of them, virtual DOM brings a lot of benefits to the table. It's comparable to the difference between programming in Python or PHP vs. programming in C. More developer ergonomy comes at the expense of performance. In other words, it's a trade-off. You inherently write more code to get the job done.&lt;br&gt;
&lt;strong&gt;2. It is not insanely performant:&lt;/strong&gt; the implementation of virtual DOM in React is not highly performant as they say. If it was, why do they have React Fiber and &lt;code&gt;shouldComponentUpdate()&lt;/code&gt;. React Fiber is basically used to optimize really heavy apps that require a lot of re-renders. the latter literally allows us to manually choose what component to update. I thought virtual DOM in React was all-encompassing, why are they providing these tools? &lt;/p&gt;

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

&lt;p&gt;And just to be clear, I have nothing against React. Virtual DOM is just another round about in updating the DOM. Yes, it's performant and it gets the job done, but i've come to realize it isn't as perfect as they say it is.&lt;/p&gt;

</description>
      <category>react</category>
      <category>svelte</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
