<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ components - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ components - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:20:18 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/components/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Share Components Between Server and Client in NextJS ]]>
                </title>
                <description>
                    <![CDATA[ Next.js App Router splits your app into Server Components and Client Components. Server Components run on the server and keep secrets safe. Client Components run in the browser and handle interactivit ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-share-components-between-server-and-client-in-nextjs/</link>
                <guid isPermaLink="false">69c6eb7c7cf27065104ba964</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Aniebo ]]>
                </dc:creator>
                <pubDate>Fri, 27 Mar 2026 20:41:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/80c9b6dc-daaa-49d5-8c3a-f61bff3b7e11.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Next.js App Router splits your app into Server Components and Client Components. Server Components run on the server and keep secrets safe. Client Components run in the browser and handle interactivity. The challenge is sharing data and UI between them without breaking the rules of each environment.</p>
<p>This guide shows you how to share components and data between Server and Client Components in Next.js. You'll learn composition patterns, prop passing rules, and when to use each approach.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-what-are-server-and-client-components">What are Server and Client Components?</a></p>
</li>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-how-to-pass-data-from-server-to-client-via-props">How to Pass Data from Server to Client via Props</a></p>
</li>
<li><p><a href="#heading-how-to-pass-server-components-as-children-to-client-components">How to Pass Server Components as Children to Client Components</a></p>
</li>
<li><p><a href="#heading-what-props-are-allowed-between-server-and-client">What Props Are Allowed Between Server and Client</a></p>
</li>
<li><p><a href="#heading-how-to-share-data-with-context-and-reactcache">How to Share Data with Context and React.cache</a></p>
</li>
<li><p><a href="#heading-how-to-use-third-party-components-in-both-environments">How to Use Third-Party Components in Both Environments</a></p>
</li>
<li><p><a href="#heading-how-to-prevent-environment-poisoning-with-server-only-and-client-only">How to Prevent Environment Poisoning with server-only and client-only</a></p>
</li>
<li><p><a href="#heading-real-world-examples">Real-World Examples</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-are-server-and-client-components">What are Server and Client Components?</h2>
<p>In the Next.js App Router, every component is a Server Component by default. Server Components run only on the server. They can fetch data from databases, use API keys, and keep sensitive logic out of the browser. They don't send JavaScript to the client, which reduces bundle size.</p>
<p>Client Components run on both the server (for the initial HTML) and the client (for interactivity). You mark them with the <code>"use client"</code> directive at the top of the file. They can use <code>useState</code>, <code>useEffect</code>, event handlers, and browser APIs like <code>localStorage</code> and <code>window</code>.</p>
<p>The key rule: <strong>Server Components can import and render Client Components, but Client Components can't import Server Components directly.</strong> They can only receive them as props (such as <code>children</code>).</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you follow along, you should have:</p>
<ul>
<li><p>Basic familiarity with React (components, props, hooks)</p>
</li>
<li><p>A Next.js project using the App Router (Next.js 13 or later)</p>
</li>
<li><p>Node.js installed (version 18 or later recommended)</p>
</li>
</ul>
<p>If you don't have a Next.js project yet, create one with:</p>
<pre><code class="language-bash">npx create-next-app@latest my-app
</code></pre>
<h2 id="heading-how-to-pass-data-from-server-to-client-via-props">How to Pass Data from Server to Client via Props</h2>
<p>The simplest way to share data between Server and Client Components is to pass it as props. The Server Component fetches the data, and the Client Component receives it and handles interactivity.</p>
<p>Here is a basic example. A page (Server Component) fetches a post and passes the like count to a <code>LikeButton</code> (Client Component):</p>
<pre><code class="language-jsx">// app/post/[id]/page.jsx (Server Component)
import LikeButton from '@/app/ui/like-button';
import { getPost } from '@/lib/data';

export default async function PostPage({ params }) {
  const { id } = await params;
  const post = await getPost(id);

  return (
    &lt;div&gt;
      &lt;h1&gt;{post.title}&lt;/h1&gt;
      &lt;p&gt;{post.content}&lt;/p&gt;
      &lt;LikeButton likes={post.likes} postId={post.id} /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/ui/like-button.jsx (Client Component)
'use client';

import { useState } from 'react';

export default function LikeButton({ likes, postId }) {
  const [count, setCount] = useState(likes);

  const handleLike = () =&gt; {
    setCount((c) =&gt; c + 1);
    // Call API or Server Action to persist
  };

  return (
    &lt;button onClick={handleLike}&gt;
      {count} likes
    &lt;/button&gt;
  );
}
</code></pre>
<p>The Server Component fetches data on the server. The Client Component receives plain values (<code>likes</code>, <code>postId</code>) and manages state and events. This pattern keeps data fetching on the server and interactivity on the client.</p>
<h2 id="heading-how-to-pass-server-components-as-children-to-client-components">How to Pass Server Components as Children to Client Components</h2>
<p>You can pass a Server Component as the <code>children</code> prop (or any prop) to a Client Component. The Server Component still renders on the server. The Client Component receives the rendered output, not the component code.</p>
<p>This is useful when you want a Client Component to wrap or control the layout of server-rendered content. For example, a modal that shows server-fetched data:</p>
<pre><code class="language-jsx">// app/ui/modal.jsx (Client Component)
'use client';

import { useState } from 'react';

export default function Modal({ children }) {
  const [isOpen, setIsOpen] = useState(false);

  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setIsOpen(true)}&gt;Open&lt;/button&gt;
      {isOpen &amp;&amp; (
        &lt;div className="modal-overlay"&gt;
          &lt;div className="modal-content"&gt;{children}&lt;/div&gt;
        &lt;/div&gt;
      )}
    &lt;/&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/cart/page.jsx (Server Component)
import Modal from '@/app/ui/modal';
import Cart from '@/app/ui/cart';

export default function CartPage() {
  return (
    &lt;Modal&gt;
      &lt;Cart /&gt;
    &lt;/Modal&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/ui/cart.jsx (Server Component - no 'use client')
import { getCart } from '@/lib/cart';

export default async function Cart() {
  const items = await getCart();

  return (
    &lt;ul&gt;
      {items.map((item) =&gt; (
        &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}
</code></pre>
<p><code>Cart</code> is a Server Component that fetches cart data. It's passed as <code>children</code> to <code>Modal</code>, which is a Client Component. The server renders <code>Cart</code> first. The RSC Payload includes the rendered result. The client receives that output and displays it inside the modal. The cart data never runs on the client.</p>
<p>You can use the same pattern with named props (slots):</p>
<pre><code class="language-jsx">// app/ui/tabs.jsx (Client Component)
'use client';

import { useState } from 'react';

export default function Tabs({ tabs, children }) {
  const [activeIndex, setActiveIndex] = useState(0);

  return (
    &lt;div&gt;
      &lt;div className="tab-list"&gt;
        {tabs.map((tab, i) =&gt; (
          &lt;button
            key={tab.id}
            onClick={() =&gt; setActiveIndex(i)}
            className={activeIndex === i ? 'active' : ''}
          &gt;
            {tab.label}
          &lt;/button&gt;
        ))}
      &lt;/div&gt;
      &lt;div className="tab-content"&gt;{children[activeIndex]}&lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/dashboard/page.jsx (Server Component)
import Tabs from '@/app/ui/tabs';
import Overview from '@/app/ui/overview';
import Analytics from '@/app/ui/analytics';

export default function DashboardPage() {
  const tabs = [
    { id: 'overview', label: 'Overview' },
    { id: 'analytics', label: 'Analytics' },
  ];

  return (
    &lt;Tabs tabs={tabs}&gt;
      &lt;Overview /&gt;
      &lt;Analytics /&gt;
    &lt;/Tabs&gt;
  );
}
</code></pre>
<p><code>Overview</code> and <code>Analytics</code> can be Server Components that fetch their own data. They render on the server, and the client receives the pre-rendered output.</p>
<h2 id="heading-what-props-are-allowed-between-server-and-client">What Props Are Allowed Between Server and Client</h2>
<p>Props passed from Server Components to Client Components must be <strong>serializable</strong>. React serializes them into the RSC Payload so they can be sent to the client.</p>
<h3 id="heading-allowed-types">Allowed Types</h3>
<ul>
<li><p>Strings, numbers, booleans</p>
</li>
<li><p><code>null</code> and <code>undefined</code></p>
</li>
<li><p>Plain objects (no functions, no class instances)</p>
</li>
<li><p>Arrays of serializable values</p>
</li>
<li><p>JSX (Server Components as children or other props)</p>
</li>
<li><p>Server Actions (functions with <code>"use server"</code>)</p>
</li>
</ul>
<h3 id="heading-not-allowed">Not Allowed</h3>
<ul>
<li><p>Functions (except Server Actions)</p>
</li>
<li><p><code>Date</code> objects</p>
</li>
<li><p>Class instances</p>
</li>
<li><p>Symbols</p>
</li>
<li><p><code>Map</code>, <code>Set</code>, <code>WeakMap</code>, <code>WeakSet</code></p>
</li>
<li><p>Objects with custom prototypes</p>
</li>
<li><p>Buffers, <code>ArrayBuffer</code>, typed arrays</p>
</li>
</ul>
<p>If you need to pass a <code>Date</code>, convert it to a string or number first:</p>
<pre><code class="language-jsx">&lt;ClientComponent createdAt={post.createdAt.toISOString()} /&gt;
</code></pre>
<p>If you use MongoDB, convert <code>ObjectId</code> to a string:</p>
<pre><code class="language-jsx">&lt;PostThread userId={user._id.toString()} /&gt;
</code></pre>
<h3 id="heading-passing-server-actions-as-props">Passing Server Actions as props</h3>
<p>Server Actions are async functions marked with <code>"use server"</code>. You can pass them as props to Client Components. They are serialized by reference, not by value.</p>
<pre><code class="language-jsx">// app/actions/post.js
'use server';

export async function likePost(postId) {
  // Update database
  revalidatePath(`/post/${postId}`);
}
</code></pre>
<pre><code class="language-jsx">// app/post/[id]/page.jsx (Server Component)
import LikeButton from '@/app/ui/like-button';
import { likePost } from '@/app/actions/post';

export default async function PostPage({ params }) {
  const post = await getPost((await params).id);

  return &lt;LikeButton likes={post.likes} postId={post.id} onLike={likePost} /&gt;;
}
</code></pre>
<pre><code class="language-jsx">// app/ui/like-button.jsx (Client Component)
'use client';

export default function LikeButton({ likes, postId, onLike }) {
  const handleClick = () =&gt; {
    onLike(postId);
  };

  return &lt;button onClick={handleClick}&gt;{likes} likes&lt;/button&gt;;
}
</code></pre>
<p>You can also bind arguments:</p>
<pre><code class="language-jsx">&lt;LikeButton onLike={likePost.bind(null, post.id)} /&gt;
</code></pre>
<h2 id="heading-how-to-share-data-with-context-and-reactcache">How to Share Data with Context and React.cache</h2>
<p>React Context doesn't work in Server Components. To share data between Server and Client Components, you can combine a Client Component context provider with <code>React.cache</code> for server-side memoization.</p>
<p>Create a cached fetch function:</p>
<pre><code class="language-js">// lib/user.js
import { cache } from 'react';

export const getUser = cache(async () =&gt; {
  const res = await fetch('https://api.example.com/user');
  return res.json();
});
</code></pre>
<p>Create a provider that accepts a promise and stores it in context:</p>
<pre><code class="language-jsx">// app/providers/user-provider.jsx
'use client';

import { createContext } from 'react';

export const UserContext = createContext(null);

export default function UserProvider({ children, userPromise }) {
  return (
    &lt;UserContext.Provider value={userPromise}&gt;
      {children}
    &lt;/UserContext.Provider&gt;
  );
}
</code></pre>
<p>In your root layout, pass the promise without awaiting it:</p>
<pre><code class="language-jsx">// app/layout.jsx
import UserProvider from '@/app/providers/user-provider';
import { getUser } from '@/lib/user';

export default function RootLayout({ children }) {
  const userPromise = getUser();

  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;UserProvider userPromise={userPromise}&gt;{children}&lt;/UserProvider&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  );
}
</code></pre>
<p>Client Components use <code>use()</code> to unwrap the promise:</p>
<pre><code class="language-jsx">// app/ui/profile.jsx
'use client';

import { use, useContext } from 'react';
import { UserContext } from '@/app/providers/user-provider';

export default function Profile() {
  const userPromise = useContext(UserContext);
  if (!userPromise) {
    throw new Error('Profile must be used within UserProvider');
  }
  const user = use(userPromise);

  return &lt;p&gt;Welcome, {user.name}&lt;/p&gt;;
}
</code></pre>
<p>Wrap the component in <code>Suspense</code> for loading states:</p>
<pre><code class="language-jsx">// app/dashboard/page.jsx
import { Suspense } from 'react';
import Profile from '@/app/ui/profile';

export default function DashboardPage() {
  return (
    &lt;Suspense fallback={&lt;div&gt;Loading profile...&lt;/div&gt;}&gt;
      &lt;Profile /&gt;
    &lt;/Suspense&gt;
  );
}
</code></pre>
<p>Server Components can call <code>getUser()</code> directly. Because it's wrapped in <code>React.cache</code>, multiple calls in the same request return the same result:</p>
<pre><code class="language-jsx">// app/settings/page.jsx
import { getUser } from '@/lib/user';

export default async function SettingsPage() {
  const user = await getUser();
  return &lt;h1&gt;Settings for {user.name}&lt;/h1&gt;;
}
</code></pre>
<p><code>React.cache</code> is scoped per request. Each request has its own memoization – there's no sharing across requests.</p>
<h2 id="heading-how-to-use-third-party-components-in-both-environments">How to Use Third-Party Components in Both Environments</h2>
<p>Some third-party components use <code>useState</code>, <code>useEffect</code>, or browser APIs but don't have <code>"use client"</code> in their source. If you use them in a Server Component, you'll get an error.</p>
<p>Wrap them in your own Client Component:</p>
<pre><code class="language-jsx">// app/ui/carousel-wrapper.jsx
'use client';

import { Carousel } from 'acme-carousel';

export default Carousel;
</code></pre>
<p>Now you can use it in a Server Component:</p>
<pre><code class="language-jsx">// app/gallery/page.jsx
import Carousel from '@/app/ui/carousel-wrapper';

export default function GalleryPage() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Gallery&lt;/h1&gt;
      &lt;Carousel /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>If the third-party component is already used inside a Client Component, you don't need a wrapper. The parent's <code>"use client"</code> boundary is enough:</p>
<pre><code class="language-jsx">'use client';

import { Carousel } from 'acme-carousel';

export default function Gallery() {
  return &lt;Carousel /&gt;;
}
</code></pre>
<h2 id="heading-how-to-prevent-environment-poisoning-with-server-only-and-client-only">How to Prevent Environment Poisoning with server-only and client-only</h2>
<p>It's easy to accidentally import server-only code (database clients, API keys) into a Client Component. To catch this at build time, use the <code>server-only</code> package.</p>
<p>Install it:</p>
<pre><code class="language-bash">npm install server-only
</code></pre>
<p>Add it at the top of files that must never run on the client:</p>
<pre><code class="language-js">// lib/data.js
import 'server-only';

export async function getSecretData() {
  const res = await fetch('https://api.example.com/data', {
    headers: {
      authorization: process.env.API_KEY,
    },
  });
  return res.json();
}
</code></pre>
<p>If you import <code>getSecretData</code> (or any symbol from this file) into a Client Component, the build will fail with a clear error.</p>
<p>For client-only code (for example, code that uses <code>window</code>), use <code>client-only</code>:</p>
<pre><code class="language-bash">npm install client-only
</code></pre>
<pre><code class="language-typescript">// lib/analytics.js
import 'client-only';

export function trackEvent(name) {
  if (typeof window !== 'undefined') {
    window.analytics?.track(name);
  }
}
</code></pre>
<p>Importing this into a Server Component will cause a build error.</p>
<h2 id="heading-real-world-examples">Real-World Examples</h2>
<h3 id="heading-example-1-layout-with-shared-server-and-client-pieces">Example 1: Layout with Shared Server and Client Pieces</h3>
<p>Keep the layout as a Server Component. Only the interactive parts are Client Components:</p>
<pre><code class="language-jsx">// app/layout.jsx (Server Component)
import Logo from '@/app/ui/logo';
import Search from '@/app/ui/search';

export default function Layout({ children }) {
  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;nav&gt;
          &lt;Logo /&gt;
          &lt;Search /&gt;
        &lt;/nav&gt;
        &lt;main&gt;{children}&lt;/main&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/ui/logo.jsx (Server Component - no directive)
export default function Logo() {
  return &lt;img src="/logo.svg" alt="Logo" /&gt;;
}
</code></pre>
<pre><code class="language-jsx">// app/ui/search.jsx (Client Component)
'use client';

import { useState } from 'react';

export default function Search() {
  const [query, setQuery] = useState('');

  return (
    &lt;input
      type="search"
      value={query}
      onChange={(e) =&gt; setQuery(e.target.value)}
    /&gt;
  );
}
</code></pre>
<p><code>Logo</code> stays on the server. <code>Search</code> is interactive and runs on the client. The layout composes both.</p>
<h3 id="heading-example-2-product-page-with-server-data-and-client-add-to-cart">Example 2: Product Page with Server Data and Client Add-to-Cart</h3>
<pre><code class="language-jsx">// app/product/[id]/page.jsx (Server Component)
import { getProduct } from '@/lib/products';
import AddToCartButton from '@/app/ui/add-to-cart-button';

export default async function ProductPage({ params }) {
  const { id } = await params;
  const product = await getProduct(id);

  return (
    &lt;div&gt;
      &lt;h1&gt;{product.name}&lt;/h1&gt;
      &lt;p&gt;{product.description}&lt;/p&gt;
      &lt;p&gt;${product.price}&lt;/p&gt;
      &lt;AddToCartButton productId={product.id} price={product.price} /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/ui/add-to-cart-button.jsx (Client Component)
'use client';

import { useState } from 'react';

export default function AddToCartButton({ productId, price }) {
  const [added, setAdded] = useState(false);

  const handleClick = () =&gt; {
    // Call Server Action or API
    setAdded(true);
  };

  return (
    &lt;button onClick={handleClick} disabled={added}&gt;
      {added ? 'Added!' : `Add to Cart - $${price}`}
    &lt;/button&gt;
  );
}
</code></pre>
<h3 id="heading-example-3-theme-provider-wrapping-server-content">Example 3: Theme Provider Wrapping Server Content</h3>
<pre><code class="language-jsx">// app/providers/theme-provider.jsx (Client Component)
'use client';

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext('light');

export function useTheme() {
  return useContext(ThemeContext);
}

export default function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  return (
    &lt;ThemeContext.Provider value={{ theme, setTheme }}&gt;
      {children}
    &lt;/ThemeContext.Provider&gt;
  );
}
</code></pre>
<pre><code class="language-jsx">// app/layout.jsx (Server Component)
import ThemeProvider from '@/app/providers/theme-provider';

export default function RootLayout({ children }) {
  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;ThemeProvider&gt;{children}&lt;/ThemeProvider&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  );
}
</code></pre>
<p><code>ThemeProvider</code> is a Client Component. It wraps <code>children</code>, which can be Server Components. Render providers as deep as possible in the tree so Next.js can optimize static Server Components.</p>
<h3 id="heading-example-4-shared-utility-without-directives">Example 4: Shared Utility Without Directives</h3>
<p>Pure utilities (no hooks, no browser APIs) can be shared. They run in the environment of the component that imports them:</p>
<pre><code class="language-js">// lib/format.js (shared - no directive)
export function formatPrice(amount) {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
  }).format(amount);
}
</code></pre>
<pre><code class="language-jsx">// Server Component
import { formatPrice } from '@/lib/format';

export default async function ProductPage() {
  const product = await getProduct();
  return &lt;p&gt;{formatPrice(product.price)}&lt;/p&gt;;
}
</code></pre>
<pre><code class="language-jsx">// Client Component
'use client';

import { formatPrice } from '@/lib/format';

export default function PriceDisplay({ amount }) {
  return &lt;span&gt;{formatPrice(amount)}&lt;/span&gt;;
}
</code></pre>
<p><code>formatPrice</code> is a pure function. It works in both Server and Client Components.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Sharing components and data between Server and Client Components in Next.js comes down to a few patterns:</p>
<ul>
<li><p><strong>Pass data as props</strong> – Server Components fetch data and pass serializable values to Client Components.</p>
</li>
<li><p><strong>Pass Server Components as children</strong> – Client Components can wrap server-rendered content via <code>children</code> or slot props.</p>
</li>
<li><p><strong>Use serializable props only</strong> – Stick to primitives, plain objects, arrays, and Server Actions. Convert <code>Date</code> and <code>ObjectId</code> to strings.</p>
</li>
<li><p><strong>Share data with Context + React.cache</strong> – Use a Client Component provider that receives a promise and <code>React.cache</code> for server-side deduplication.</p>
</li>
<li><p><strong>Wrap third-party components</strong> – Add <code>"use client"</code> wrappers for libraries that use client-only features.</p>
</li>
<li><p><strong>Use server-only and client-only</strong> – Prevent accidental imports across the server/client boundary.</p>
</li>
</ul>
<p>Keep Server Components at the top of the tree and push Client Components down to leaf nodes. This reduces JavaScript sent to the browser while keeping interactivity where you need it.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Extend Power Apps with Reusable Components ]]>
                </title>
                <description>
                    <![CDATA[ If you have experience in traditional software development, low-code tools may feel a bit sparse at first. But to many people’s surprise, traditional techniques often translate quite well to low-code  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/powerapps-component-crash-course/</link>
                <guid isPermaLink="false">682779afad5694b25984f6b1</guid>
                
                    <category>
                        <![CDATA[ Canvas PowerApps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Low Code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Brandon Wozniewicz ]]>
                </dc:creator>
                <pubDate>Fri, 16 May 2025 17:45:19 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747410099474/8471a651-503f-4ced-a172-7dadac930039.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you have experience in traditional software development, low-code tools may feel a bit sparse at first. But to many people’s surprise, traditional techniques often translate quite well to low-code development. Not always one-for-one – but usually close enough.</p>
<p>One of the most fundamental tasks when building an application is breaking it down into its core parts, or components. Websites are constructed from smaller building blocks. Just how small? Well, that’s up to you, the developer.</p>
<p>In the example below, we can spot some obvious elements: a header, a search box, perhaps a sidebar for navigation, and a main content area. Applications emerge from many smaller parts coming together.</p>
<img src="https://www.scriptedbytes.com/content/images/2025/05/components.png" alt="Image of components of a website" width="600" height="400" loading="lazy">

<p>Components allow us to isolate responsibility and manage complexity for specific parts of an application. In both traditional and low-code development, they play a vital role in creating maintainable, reusable, and testable products.</p>
<p>In this article, you’ll learn what a component is. Then we’ll build a custom text field component inside a Canvas app.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>This tutorial assumes a basic understanding of Microsoft Power Apps. While not required to understand the article, to actively follow along, you’ll need access to a Power Platform environment with the App Maker security role.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a href="#heading-the-concept-of-a-component">The Concept of a Component</a></p>
</li>
<li><p><a href="#heading-how-to-build-your-own-component">How to Build Your Own Component</a></p>
</li>
<li><p><a href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-the-concept-of-a-component">The Concept of a Component</h2>
<p>The idea of components isn’t new – and it’s not exclusive to software.</p>
<p>Let’s think about a car for a moment. A car is made up of many smaller parts: wheels, an engine, seats, a steering wheel, and so on. But it’s the concept of the car – and specifically its ability to transport us – that provides value. That concept emerges from the way the individual parts work together.</p>
<p>Now imagine you get a flat tire. Not a good day. But thanks to how cars are designed, you don’t need a whole new car – maybe not even a new tire. You fix the issue and you’re back on the road within a few hours. Breaking things into smaller parts helps make the whole system more resilient. Applying this same principle to application development is a smart, future-proof approach.</p>
<h3 id="heading-two-broad-types-of-components">Two Broad Types of Components</h3>
<p>Within an application, components can vary in complexity and responsibility. Some are simple, like a text label. Others are more complex, like a pop-up dialog. Regardless of their complexity (again, your design choice), components typically fall into one of two categories:</p>
<ul>
<li><p><strong>Presentational ("Dumb") Components</strong></p>
</li>
<li><p><strong>Container ("Smart") Components</strong></p>
</li>
</ul>
<p>The difference comes down to purpose. A container component may interact with external sources and usually mutates state. A presentational component, on the other hand, is generally only responsible for how things look and light communication with the application.</p>
<p>Container components are often more complex and harder to test. Presentational components are typically simpler and more predictable.</p>
<p>This isn’t to say you should avoid container components. That’s not realistic. At some point, your app will need to talk to the outside world.</p>
<h3 id="heading-aside-pure-functions">Aside: Pure Functions</h3>
<p>The concept of <strong>pure functions</strong> is useful here.</p>
<p>A function is considered <em>pure</em> if it always returns the same output for the same input and doesn’t interact with any external state.</p>
<pre><code class="language-JavaScript">// Example 1 (pure)
function add(x, y) {
  return x + y;
}

console.log(add(2, 3)); // Always 5

// Example 2 (not pure)
function subtract(x) {
  const y = Math.floor(Math.random() * 100) + 1; // Random number between 1 - 100
  console.log(y);
  return x + y;
}

console.log(subtract(5)); // Unpredictable
</code></pre>
<p>Just like <code>add()</code> is pure and <code>subtract()</code> is not, a presentational component behaves like a pure function: same input, same output. The output might be how the UI appears or an event with associated data.</p>
<h3 id="heading-more-about-inputs-and-outputs">More About Inputs and Outputs</h3>
<p>If you’ve built a Canvas App before, you’ve already used components – even if you didn’t realize it. Most controls in a Canvas App are presentational components.</p>
<p>Take the <strong>Label</strong> control. It receives an input (<code>Text</code>) and renders output (the text on screen).</p>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_37f5d6fa.png" alt="Image of Canvas App label" width="600" height="400" loading="lazy">

<p>Events are another kind of output. For example, the <strong>Button</strong> control emits an event when clicked – handled through the <code>OnSelect</code> property. That property allows the app to respond to the click and perform some logic.</p>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_37fa1150.png" alt="Image of Canvas app button" width="600" height="400" loading="lazy">

<p>💡 When a component sends a message back to the application the component is said to have <em>emitted an event.</em></p>
<p>Now let’s look at the <strong>Text Input</strong> control.</p>
<p>Like the others, it has inputs (like <code>Placeholder</code>). But it also emits a <code>Change</code> event via <code>OnChange</code>. Even better, it passes data back to the application through its <code>Value</code> property. As the user types, the value updates. That value is how we access what they typed.</p>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_38070a2d.png" alt="Image of Canvas app text input" width="600" height="400" loading="lazy">

<h2 id="heading-how-to-build-your-own-component">How to Build Your Own Component</h2>
<p>Let’s build a simple, customized input component. It will include:</p>
<ul>
<li><p>A label above the input</p>
</li>
<li><p>Optional “required” validation</p>
</li>
<li><p>Change detection and data output</p>
</li>
</ul>
<p>Here is what it will look like:</p>
<img src="https://www.scriptedbytes.com/content/images/2025/05/image.png" alt="Image of custom text field to be built" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<h3 id="heading-part-1-create-the-component">Part 1: Create the Component</h3>
<ol>
<li><p>Navigate to the <strong>Components</strong> section of your Canvas App.</p>
</li>
<li><p>Add a new component and name it <code>cmp_baseInput</code>.</p>
</li>
<li><p>Resize it to 340 (w) x 100 (h).</p>
</li>
</ol>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_3819d94d.png" alt="Image of how to create a component" width="600" height="400" loading="lazy">

<h3 id="heading-part-2-add-controls">Part 2: Add Controls</h3>
<ol>
<li><p>Add a <strong>Text Input</strong> control, centered.</p>
</li>
<li><p>Add two <strong>Labels</strong>—one above, one below the input.</p>
</li>
<li><p>Rename them:</p>
<ul>
<li><p><code>lbl_label</code></p>
</li>
<li><p><code>lbl_hint</code></p>
</li>
<li><p><code>txt_textField</code></p>
</li>
</ul>
</li>
</ol>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_381d4ce8.png" alt="Image of the appropriate controls added to the component" width="600" height="400" loading="lazy">

<h3 id="heading-part-3-add-custom-properties">Part 3: Add Custom Properties</h3>
<p>Add four properties to the component. We're primarily concerned with the Property Type, Property Definition, and Data Type properties.</p>
<ul>
<li><p><code>IsRequired</code> (Data, Input, Boolean)</p>
</li>
<li><p><code>Label</code> (Data, Input, Text)</p>
</li>
<li><p><code>Value</code> (Data, Output, Text)</p>
</li>
<li><p><code>OnChange</code> (Event)</p>
</li>
</ul>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_38262956.png" alt="Image of custom properties added to the component" width="600" height="400" loading="lazy">

<h3 id="heading-part-4-connect-the-properties">Part 4: Connect the Properties</h3>
<p>Set the control's properties as follows.</p>
<pre><code class="language-plaintext">lbl_label.Text = cmp_baseInput.Label

lbl_hint.Text = "This field is required."
lbl_hint.Visible = cmp_baseInput.IsRequired And Len(txt_textField.Value) &lt; 1

txt_textField.OnChange = cmp_baseInput.OnChange()

cmp_baseInput.Value = txt_textField.Value
cmp_baseInput.Label = "Placeholder Label"
</code></pre>
<h3 id="heading-part-5-style-it">Part 5: Style It</h3>
<pre><code class="language-plaintext">lbl_label.Size = 12
lbl_label.Height = 24
lbl_label.FontColor = RGBA(122, 138, 143, 1)

lbl_hint.Size = 10
lbl_hint.Height = 24
lbl_hint.FontColor = RGBA(215, 58, 60, 1)
lbl_hint.FontWeight = 'TextCanvas.Weight'.Semibold
</code></pre>
<h3 id="heading-part-6-add-it-to-the-app">Part 6: Add It to the App</h3>
<ol>
<li><p>Go back to the application screen.</p>
</li>
<li><p>Insert the component and name it <code>cmp_userName</code>.</p>
</li>
<li><p>Add a label nearby and set its text to:<br><code>"The user name is: " &amp; cmp_userName.Value</code></p>
</li>
</ol>
<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_3835242d.png" alt="Image of inserting the component in the application" width="600" height="400" loading="lazy">

<img src="https://www.scriptedbytes.com/content/images/2025/05/Snag_383a4039.png" alt="Image of the component inserted into the application" width="600" height="400" loading="lazy">

<h3 id="heading-part-7-test-it">Part 7: Test It</h3>
<ul>
<li><p>Type in the component and click outside of it → label near the component updates and the hint disappears.</p>
</li>
<li><p>Clear the text → hint reappears</p>
</li>
<li><p>Set <code>IsRequired</code> to false → hint disappears</p>
</li>
<li><p>Set <code>OnChange</code> to <code>Notify("A change occurred!")</code> and type in the input→ a toast message appears with you notification.</p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>You’ve just created a functional, presentational component. It handles labels, validation, value output, and even events – all in one package.</p>
<p>This is the real power of components: abstraction, clarity, and reusability. Whether you're in a traditional or low-code environment, thinking in components helps you break complexity into manageable parts.</p>
<p>As your apps grow, this mindset will pay off. You'll spend less time rewriting logic and more time building value – one well-defined part at a time.</p>
<p>Found this helpful? I write about practical automation, productivity systems, and building smarter workflows — without the jargon. Visit me at <a href="http://brandonwoz.com">brandonwoz.com</a>.</p>
<p><em>Stay curious and keep building.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Move Figma Components to Penpot ]]>
                </title>
                <description>
                    <![CDATA[ Penpot is an open-source design tool for creating complete design systems. It is free, self-hostable, and allows multiple projects. Penpot supports reusable components and assets and allows files and libraries to be shared across projects. Penpot fil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-recreate-figma-components-in-penpot/</link>
                <guid isPermaLink="false">67e48bc10d600bc3806ccf54</guid>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Open Source ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Penpot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ figma ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Fatuma Abdullahi ]]>
                </dc:creator>
                <pubDate>Wed, 26 Mar 2025 23:20:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743028701920/ef200f8f-888d-4658-a5b0-ffa483edbdcf.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://penpot.app/">Penpot</a> is an open-source design tool for creating complete design systems. It is free, self-hostable, and allows multiple projects. Penpot supports reusable components and assets and allows files and libraries to be shared across projects. Penpot files can be exported in various formats to enhance collaboration.</p>
<p>Penpot designs directly translate to code that meets web standards, facilitating collaboration and hand-off between designers and developers.</p>
<p>This tutorial will walk you through recreating or moving existing <a target="_blank" href="https://www.figma.com/">Figma</a> components to Penpot. It will include a rundown of the Penpot tool and how to use it, a brief comparison of the two tools, and important resources.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-recreate-existing-figma-files-in-penpot">How to Recreate Existing Figma Files in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-penpot-user-interface">Understanding the Penpot User Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-penpot-layouts">Understanding Penpot Layouts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-and-use-penpot-components">How to Create and Use Penpot Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-reusable-assets-in-penpot">How to Create Reusable Assets in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-and-use-icons-in-penpot">How to Add and Use Icons in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-figma-vs-penpot-my-experience">Figma Vs. Penpot - My experience</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resources-and-notes">Resources and Notes</a></p>
</li>
</ul>
<h2 id="heading-how-to-recreate-existing-figma-files-in-penpot">How to Recreate Existing Figma Files in Penpot</h2>
<p>There are two ways to move or recreate existing Codex components from Figma to Penpot: By using the community-supported migration tool or by manually recreating the components and files.</p>
<h3 id="heading-using-the-community-supported-migration-plugin">Using the Community-Supported Migration Plugin</h3>
<p>You can use <a target="_blank" href="https://www.figma.com/community/plugin/1219369440655168734/penpot-exporter">this plugin</a> to move your Figma designs to Penpot. It is a straightforward way to migrate from Figma, especially if you have many components.</p>
<p>To do so, add it as a Figma plugin and find the option in the context menu. Then, click on the "Penpot Exporter" option to activate the plugin. The plugin will then create a zip file for your component and download it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571496007/da97ad1b-6939-4bb9-9000-6c367a711797.gif" alt="A screenrecording illustrating how to add and use the &quot;Penpot Exporter&quot; plugin." class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Over in Penpot, in your Projects dashboard, click on the three dots context menu and select "Import Penpot files" to open a file picker window. Click on the zip file downloaded from Figma, and Penpot will create a new project with the same name as the zip file. This new project will contain your Figma component translated to the Penpot environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571779644/1ebeb54d-ce27-4987-b630-f101a60ee8d3.gif" alt="An illustration of how to import files to Penpot" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Looking at the new component, you'll notice that the migration plugin correctly picks up any child components and typography variables while keeping things fairly organized. But it does not pick up color variables.</p>
<h3 id="heading-manually-recreating-figma-components">Manually Recreating Figma components</h3>
<p>Another way to move Figma components to Penpot is to recreate them manually. While this option is more tedious than the previous one, it gives you fine-tuned control over how the component looks, how the files are organized, and how the assets are carried over.</p>
<p>It is an excellent excuse to spruce up the existing components, especially if there are few. It is also a good exercise for first-time users to grasp Penpot.</p>
<p>To effectively move components using this method, you will need to understand how Penpot works. The following concepts will help make this process more efficient.</p>
<h2 id="heading-understanding-the-penpot-user-interface">Understanding the Penpot User Interface</h2>
<p>Penpot's UI is pretty similar to Figma's, except that Penpot defaults to Dark Mode. You have your controls on the right and your files, assets, and layers on the left, with a canvas in the middle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742811019699/ea5336e3-50a7-4771-bfa6-07a225390320.png" alt="Alt: Screenshot of a Penpot UI with a left panel labeled &quot;Layers&quot; showing file structure, a central canvas labeled &quot;Canvas,&quot; and a right panel with various design tools and settings." class="image--center mx-auto" width="1600" height="620" loading="lazy"></p>
<p>Both have a toolbar that enables you to interact with the canvas. The toolbars have slightly different icons and names but have the same functionality. Notably, in Penpot, the Frame tool is called Board.</p>
<p>Penpot supports most of Figma's features, except for Design Tokens, which will be added soon.</p>
<h2 id="heading-understanding-penpot-layouts">Understanding Penpot Layouts</h2>
<p>Penpot supports Flex and Grid layouts. These layouts allow you to position items precisely and simplify creating fluid designs. For those familiar with CSS Grid and Flex, they work in the same way.</p>
<p>Flex layout allows you to organize the elements within a parent container, like a board or an encompassing shape, across one dimension, width, or height. It enables you to determine the spacing and positioning of the child elements via visual controls with labels on the right side panel.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571904634/c8bf8fc0-79a7-415f-916b-42da7c881ed8.gif" alt="An illustration on how to use Penpot Flex Layout" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Grid layouts allow the same controls as Flex layouts but with the added flexibility of simultaneously spanning a child element across both dimensions. This makes Grid layouts quite helpful in creating complex and nuanced designs.</p>
<h2 id="heading-how-to-create-and-use-penpot-components">How to Create and Use Penpot Components</h2>
<p>Creating a component in Penpot is relatively straightforward. You select the elements that will make up the component, then right-click and click "Create component," turning your selection into a component.</p>
<p>Your new component will be available under the "Assets" tab on the left side panel. To use, drag it onto the canvas.</p>
<p>You can also create copies of the component. By default, the copies are tied to the main component, and any changes to the main will be reflected in all copies. You can override this by detaching the copies from the context menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571991986/6dd4820b-0f3a-4d41-895d-cb9f5e7d4f52.gif" alt="A speedrun of how to create a Penpot Component" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<h2 id="heading-how-to-create-reusable-assets-in-penpot">How to Create Reusable Assets in Penpot</h2>
<p>Penpot has three asset types: Typography, Colors, and Components, with <a target="_blank" href="https://penpot.app/collaboration/design-tokens">Penpot design tokens</a> coming very soon. Typography refers to information on font types and weights that make up text styles. Colors enable you to create and sort your repeated colors. Components refer to reusable design pieces and, in this context, include graphical items like icons and images.</p>
<p>To create a color or typography asset, click the "Assets" tab and the plus icon on the relevant accordion item. For color, it will open a color picker. Paste the hex value in the appropriate place, then save it. The color will show up in the accordion drop-down. You can click on it to give it a semantic name if desired.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742809861347/9ae3b0fb-798b-4363-ab90-873c18a16793.png" alt="Screenshot of a Penpot UI showing a color palette with hex codes, a color picker, and local library assets." class="image--center mx-auto" width="976" height="800" loading="lazy"></p>
<p>For typography, click on the plus icon at the relevant accordion. This will open a panel where you can specify the font, font weight, letter spacing, and line height. You can also change the asset's name after it's saved.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742810318737/daf0e24f-7c4a-4c00-bb73-ccca7575bcf5.png" alt="daf0e24f-7c4a-4c00-bb73-ccca7575bcf5" class="image--center mx-auto" width="443" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-and-use-icons-in-penpot">How to Add and Use Icons in Penpot</h2>
<p>You can add icon packs and libraries in Penpot from the Project dashboard. At the bottom of the page, a banner containing a list of commonly used libraries is displayed. These libraries usually include a few icon packs. You can scroll through to choose one or click on the explore more option at the end of the slider to open up the dedicated Penpot templates page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742810534992/83b2eb72-4877-49b3-9d2e-02c37e0cb894.png" alt="Screenshot of Penpot UI's lower bottom showing &quot;Penpot - Design System v2.0&quot;, &quot;New Project 1&quot;, &quot;Avataaars&quot;, &quot;UX Notes&quot;, &quot;Whiteboarding Kit&quot;, &quot;Open Color Scheme&quot;, and &quot;Flex Layout Playground&quot;. A sidebar labeled &quot;Libraries &amp; Templates&quot; is visible on the right." class="image--center mx-auto" width="900" height="282" loading="lazy"></p>
<p>If you find a relevant library from the bottom banner, click the download icon. Penpot will prompt you to add the selected library. Once you accept it, it will be added to the "Libraries" menu item on the left side panel.</p>
<p>If you click through to the dedicated templates page, clicking the download icon will download a Penpot file. You can then drag it to the projects page, and it will also be available in the "Libraries" section of the projects page.</p>
<p>To use the libraries within your project file, click the "Assets" tab on the left side panel, then click the "Libraries" button below it. This will open a modal with all your libraries listed under "Shared Libraries."</p>
<p>Click on the plus icon on the ones you want to use in your project. This will link that library to your project and be available in the left side panel. You can then search for any particular icon from the search bar and drag it onto the canvas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571300138/3dbbc937-f727-4c03-987b-43ddb71b1608.gif" alt="A gif illustrating how to link and delink libraries in the Penpot User Interface" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>To remove a library from your project, click on the libraries button. In the modal, under "libraries in this file," all used libraries are listed. Click on the link icon next to the library you want to remove. This will delink it and remove it from the side panel.</p>
<h2 id="heading-figma-vs-penpot-my-experience">Figma Vs. Penpot – My experience</h2>
<p>As a first-time user of Penpot and a long-term casual user of Figma, I noticed some differences and encountered some teething problems.</p>
<h3 id="heading-swapping-out-icons">Swapping Out Icons</h3>
<p>You can <a target="_blank" href="https://help.penpot.app/user-guide/components/#component-swap">swap out components</a> in Penpot! It's too bad that I discovered this after I had finished my first component migration.</p>
<h3 id="heading-renaming-files-and-folders">Renaming Files and Folders</h3>
<p>I struggled to find how to rename files and folders in Penpot. I kept looking for the shortcut or a menu item in the context menu. It turns out you have to double-click on the title to change it. You can rename files in the same way in Figma, but I just never did it like that.</p>
<h3 id="heading-adherence-to-web-standards">Adherence to Web Standards</h3>
<p>I was pleasantly surprised at the code quality that Penpot provides, along with your designs. It meets the <a target="_blank" href="https://www.w3.org/standards/">w3c standards</a>, but the HTML could be more <a target="_blank" href="https://web.dev/learn/html/semantic-html">semantic</a>.</p>
<h3 id="heading-penpot-design-system">Penpot Design System</h3>
<p>Penpot avails its <a target="_blank" href="https://community.penpot.app/t/pencil-the-penpot-design-system/7152">design system</a> along with lots of little libraries that help you understand how the tool works. This is very nice as it allows you to get a good understanding of design language and how to organize design systems.</p>
<h3 id="heading-limited-shape-options-in-the-toolbar">Limited Shape Options in the Toolbar</h3>
<p>The Penpot toolbar lacks essential shapes such as pen, arrow, and triangle. While you can recreate this with the path tool or use a library to import them, it is definitely something I missed that was readily available in Figma.</p>
<p>It took me a few tries to get comfortable with Penpot and in the end, I really liked it. Plus, its open-source nature makes it even more endearing.</p>
<h2 id="heading-resources-and-notes">Resources and Notes</h2>
<p>Using Penpot has a learning curve, even if you are familiar with other design tools like Figma. These resources can help you get up to speed faster and make you more efficient with Penpot.</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/live/64O8qi51Jqc?si=A6AVp1m8se3gl1ut">Penpot video on layouts</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/aW0LNHLEI_Y?si=HATAWee8tH29Sgrq&amp;t=1604">Penpot live on design tokens</a></p>
</li>
<li><p><a target="_blank" href="https://help.penpot.app/user-guide/">Penpot documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.figma.com/community/plugin/1219369440655168734/penpot-exporter">Penpot migration plugin</a></p>
</li>
<li><p><a target="_blank" href="https://penpot.app/libraries-templates">Penpot templates and libraries</a></p>
</li>
<li><p><a target="_blank" href="https://penpot.app/blog/penpot-for-design-systems-101/">Penpot design systems</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a CSS Component Library and Improve Your Web Development Skills ]]>
                </title>
                <description>
                    <![CDATA[ Application development is a complex, multi-stage process, and it all begins with UI/UX design. Once the design phase is complete, the focus shifts to UI development, where tools like HTML, CSS, and JavaScript come into play. At a higher level, libra... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-css-component-library-step-by-step/</link>
                <guid isPermaLink="false">6709799c031bde0105c6130f</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Prankur Pandey ]]>
                </dc:creator>
                <pubDate>Fri, 11 Oct 2024 19:16:44 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728400677433/de06f432-0861-4ba4-ad7c-6e10157e2822.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Application development is a complex, multi-stage process, and it all begins with UI/UX design.</p>
<p>Once the design phase is complete, the focus shifts to <strong>UI development</strong>, where tools like <strong>HTML</strong>, <strong>CSS</strong>, and <strong>JavaScript</strong> come into play. At a higher level, libraries like <strong>React</strong> and <strong>Vue</strong> streamline the development process.</p>
<p>Regardless of the application type, your code can almost always be broken down into <strong>components</strong>.</p>
<p><em>“Repeated components are a nightmare to manage.”</em> – Every frustrated UI developer</p>
<p>Imagine having a component library where all commonly used elements are pre-built and responsive—how much easier and faster would that make development?</p>
<p>In this article, I’ll show you how to build your own component library, using a minimal tech stack, and then use it to build an application.</p>
<h3 id="heading-what-well-cover">What We’ll Cover</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-build-a-component-library">Why Build a Component Library</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-component-library">How to Build the Component Library</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-lets-build-the-library">Let’s Build the Library</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-design-the-layout-using-pen-and-paper">Step 1: Design the Layout using Pen and Paper</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-design-the-components-in-html-and-css">Step 2: Design the Components in HTML and CSS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-hosting-the-project-css-file">Step 3: Hosting the Project CSS File</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-faq">FAQ</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p><strong>Proficiency in HTML, CSS, and JavaScript</strong>: A solid understanding of front-end development fundamentals is essential.</p>
</li>
<li><p><strong>Basic Deployment Skills</strong>: Familiarity with deploying applications on platforms like <strong>Netlify</strong> or <strong>Vercel</strong> is required.</p>
</li>
<li><p><strong>Git/GitHub Knowledge</strong>: You should be comfortable with version control, including basic Git commands and managing repositories on GitHub.</p>
</li>
</ul>
<h2 id="heading-why-build-a-component-library">Why Build a Component Library?</h2>
<p>Every website is built from components, which are structured with <strong>HTML</strong> and styled using <strong>CSS</strong>.</p>
<p><strong>HTML</strong> and <strong>CSS</strong> are fundamental technologies for creating visually appealing web pages. However, mastering them can be challenging due to the wide array of HTML tags and CSS properties.</p>
<p>To simplify the process, developers often use <strong>component libraries</strong>, which deliver various benefits:</p>
<ol>
<li><p><strong>Faster Development</strong>: Pre-built components and responsive design features accelerate the development process.</p>
</li>
<li><p><strong>Consistency</strong>: Ensures uniform styling and cross-browser compatibility across the application.</p>
</li>
<li><p><strong>Maintainability</strong>: Encourages structured, modular code, making it easier to maintain and scale.</p>
</li>
<li><p><strong>Community Support</strong>: extensive documentation, plugins, and a strong community provide valuable resources.</p>
</li>
<li><p><strong>Customization and Accessibility</strong>: offers easy customization and accessibility-focused components for inclusive designs.</p>
</li>
</ol>
<h2 id="heading-how-to-build-the-component-library">How to Build the Component Library</h2>
<p>Building a component library involves several key steps. First, I’ll give you an overview of each step we’ll take to create the component library. After that, we’ll build it together.</p>
<h3 id="heading-1-design-the-layout-of-the-components">1. Design the Layout of the Components</h3>
<p>Before writing any code, it’s crucial to have a clear vision of what you want to build. Start by sketching the layout of your components on paper, or use design tools like <strong>Figma</strong> or <strong>Canva</strong> to create a visual representation.</p>
<p>Having a visual guide will streamline your coding process and help you stay focused as you translate designs into code.</p>
<h3 id="heading-2-write-the-component-structure-in-html">2. Write the Component Structure in HTML</h3>
<p>Once the design is ready, the next step is to structure your components in <strong>HTML</strong>. This creates the foundation of your webpage, as HTML is the backbone of any web project.</p>
<p><strong>Pro-tip</strong>: Use <strong>semantic HTML</strong> to improve user accessibility and SEO. For example, use <code>&lt;article&gt;</code>, <code>&lt;section&gt;</code>, or <code>&lt;header&gt;</code> tags instead of generic <code>&lt;div&gt;</code> elements when appropriate.</p>
<h3 id="heading-3-style-the-components-with-css">3. Style the Components with CSS</h3>
<p>With the HTML structure in place, you can begin styling the components using <strong>CSS</strong>. Apply styles like <strong>background colours</strong>, <strong>font sizes</strong>, <strong>link decorations</strong>, and <strong>button styles</strong> using <strong>CSS classes</strong> and <strong>IDs</strong>.</p>
<p>CSS is a powerful tool—you can even add beautiful animations. But in this tutorial, we’ll focus on utilizing the essential properties of CSS to create clean, functional designs.</p>
<h3 id="heading-4-host-the-projects-css-file">4. Host the Project's CSS File</h3>
<p>Once your component library is ready, you’ll want to make it accessible for future projects. Hosting your <strong>CSS file</strong> on platforms like <strong>Netlify</strong>, <strong>GitHub Pages</strong>, or <strong>Vercel</strong> allows you to use the components across different projects by simply linking to the global CSS file.</p>
<p>By following these four steps, you’ll create a reusable component library that helps you build beautiful websites efficiently and effectively.</p>
<h2 id="heading-lets-build-the-library">Let’s Build the Library</h2>
<p>I began my journey as a software developer by diving into <strong>HTML</strong> and <strong>CSS</strong> to design webpages. These foundational technologies are essential for any web developer, but mastering them can be challenging—HTML boasts 152 tags, while CSS has over 200 properties.</p>
<p>While you won’t need to use every single HTML tag or CSS property, knowing the core concepts requires significant time and effort. .</p>
<p>Now, let’s consider a scenario: if I asked you to create a small website or a landing page without using any component library, how would you approach it? My goal is to minimize the time spent on designing.</p>
<p>Imagine if there was a way to automate the design process, allowing you to achieve beautiful results without sacrificing flexibility. This is where a <strong>component library</strong> comes into play. By writing your components in pure vanilla CSS once, you can reuse them across any project.</p>
<p>I encourage you to pursue this approach because it will provide real-time experience with HTML and CSS while helping you learn a multitude of concepts simultaneously.</p>
<p>I developed a small library consisting of 10+ beautiful components, which you can explore here: <a class="post-section-overview" href="#"><strong>SlateUi</strong></a>. This library has helped deepen my understanding of web technologies.</p>
<p>My goal was to understand HTML and CSS thoroughly. After completing one project, I wanted to feel confident in all the critical aspects of web design, from UI to code.</p>
<p>By designing and developing these components, I gained greater control and customization options tailored to specific requirements.</p>
<p>The learning process was also incredibly rewarding. Creating each component took considerable time, but the exposure I gained to these two technologies significantly boosted my confidence.</p>
<p>Additionally, this approach helps avoid the redundancy of writing repetitive CSS code for similar elements.</p>
<h3 id="heading-step-1-design-the-layout-using-pen-and-paper">Step 1: Design the Layout using Pen and Paper</h3>
<p>First, you’ll want to create a basic layout for the webpage. This is just initial sketching so that you know what you have to build in your project</p>
<p>The layout consists of three key elements:</p>
<p>a) <strong>Header</strong><br>b) <strong>Card(s)</strong><br>c) <strong>Footer</strong></p>
<p>Each component includes distinct colours, text, and additional elements. Here’s what it looks like in our example:</p>
<p><a target="_blank" href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcqxm4mrnyx778sedui.png"><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcqxm4mrnyx778sedui.png" alt="Illustration of the main components of the layout: header, card, footer" width="800" height="400" loading="lazy"></a></p>
<p>In an actual project, you typically start with prepared design models created in tools like <strong>Figma</strong> or other UI design software.</p>
<p>For this project, I used <strong>Canva</strong> to design the layout. This initial design phase is crucial as it lays the foundation for core feature development.</p>
<p>Then, you’ll write the structure of the component in HTML. At this level, I will simply put our HTML elements in such a way so that we can prepare a basic skeleton of the webpage as we have designed it. In the header I have a logo and some navigation links, in the cards I have a button and an image; and in the footer, I have some more links.</p>
<h3 id="heading-step-2-design-the-components-in-html-and-css">Step 2: Design the Components in HTML and CSS</h3>
<p>At this point<strong>,</strong> we’ll enhance the components we created with HTML by applying CSS properties to beautify them. This stage involves using CSS to set background colours, primary colours, link decorations, button styles, and more. We’ll do this by utilizing CSS classes and IDs.</p>
<p>So far, we’ve built three components:</p>
<p>a) <strong>Header</strong> with navigation links<br>b) <strong>Footer</strong><br>c) <strong>Horizontal Cards</strong> with action buttons</p>
<p>Now, let’s begin by building the first component: the <strong>Header</strong>.</p>
<h4 id="heading-the-header-component">The header component:</h4>
<p>The header is at the top of a page or a section. It usually contains a logo, search bar, navigational links, and so on.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/iprankurpandey/embed/eYVzNPR?default-tab=html" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/iprankurpandey/pen/eYVzNPR">
  Header</a> by PRANKUR PANDEY (<a href="https://codepen.io/iprankurpandey">@iprankurpandey</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<h4 id="heading-the-footer-component">The footer component:</h4>
<p>The Footer defines the footer or bottom of a web page or a section. Usually, it contains copyright information, contact details, navigation links, and so on.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/iprankurpandey/embed/poabJqN?default-tab=html" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/iprankurpandey/pen/poabJqN">
  Footer</a> by PRANKUR PANDEY (<a href="https://codepen.io/iprankurpandey">@iprankurpandey</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<h4 id="heading-the-card-component">The card component:</h4>
<p>The <strong>card component</strong> can house various types of content, including a heading, image, main content, and a footer that features a call-to-action button.</p>
<p>Cards are designed to serve specific purposes, such as showcasing e-commerce products, displaying news items, or serving multiple other functions across different contexts.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/iprankurpandey/embed/KKQMpvd?default-tab=html" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/iprankurpandey/pen/KKQMpvd">
  Horizontal-Cards</a> by PRANKUR PANDEY (<a href="https://codepen.io/iprankurpandey">@iprankurpandey</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<h4 id="heading-combining-it-all-together">Combining it all together:</h4>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/iprankurpandey/embed/NWyrjGm?default-tab=html" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/iprankurpandey/pen/NWyrjGm">
  Demo-API</a> by PRANKUR PANDEY (<a href="https://codepen.io/iprankurpandey">@iprankurpandey</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>By clicking the button, the card data will update with random cat facts, along with the length of each fact.</p>
<p><strong>Note</strong>: I used an open-source API for this project. If the content does not update on the card, it may be due to an API outage.</p>
<p>Now, have you checked the CSS code?</p>
<p>You might be wondering why I’ve imported just a single line of code into my CSS file. Well, I have combined the CSS files of all three parts of the layout (<strong>header, footer, &amp; cards</strong> components) into one CSS file and hosted the file on Netlify. This is the URL that is holding all three CSS files:</p>
<p><code>@import url("</code><a target="_blank" href="https://hashnodeblogchallenge.netlify.app/index.css"><code>https://hashnodeblogchallenge.netlify.app/index.css</code></a><code>");</code></p>
<p>It serves the CSS in all three components and maintains the styles for all three components.</p>
<h3 id="heading-step-3-hosting-the-project-css-file">Step 3: Hosting the Project CSS File</h3>
<p>Finally, I’ve arrived at the most crucial part of this project, where all the magic happens.</p>
<p>Currently, I have three CSS files for each of the web components: <strong>header</strong>, <strong>cards</strong>, and <strong>footer</strong>.</p>
<p>Since our project is small, I will combine all CSS file code into one CSS file to get one CSS file which will work as a universal CSS file.</p>
<p>The process of hosting the CSS file is straightforward. Here's a detailed breakdown of what you need to do:</p>
<h4 id="heading-1-push-your-code-to-github">1. <strong>Push Your Code to GitHub</strong></h4>
<p>You need to push (upload) your project files, including the HTML, CSS, and other assets, to a GitHub repository. Here’s how you can do that:</p>
<ol>
<li><p>Initialize a Git repository in your project directory using <code>git init</code>.</p>
</li>
<li><p>Add all your files using <code>git add .</code>.</p>
</li>
<li><p>Commit the files with <code>git commit -m "Initial commit"</code>.</p>
</li>
<li><p>Link to a GitHub repository you’ve created using <code>git remote add origin &lt;repo-url&gt;</code>.</p>
</li>
<li><p>Finally, push your code using <code>git push -u origin main</code>.</p>
</li>
<li><p><strong>Result</strong>: Your project files will now be hosted in your GitHub repository.</p>
</li>
</ol>
<h4 id="heading-2-open-netlify-and-log-in-or-sign-up">2. <strong>Open Netlify and Log In or Sign Up</strong></h4>
<p>Then, visit <a target="_blank" href="https://www.netlify.com">Netlify</a> and either sign in if you already have an account or create a new one.</p>
<p>You can sign up using your GitHub credentials or a separate email. This step gives you access to Netlify's web hosting services, which will allow you to deploy your project directly from GitHub.</p>
<h4 id="heading-3-connect-your-github-repository-that-contains-your-code">3. <strong>Connect Your GitHub Repository That Contains Your Code</strong></h4>
<p>Once logged in, you'll connect your GitHub repository to Netlify.</p>
<ol>
<li><p>On Netlify, click on "New site from Git".</p>
</li>
<li><p>Choose <strong>GitHub</strong> as the source.</p>
</li>
<li><p>Authorize Netlify to access your GitHub account.</p>
</li>
<li><p>Select the repository that contains your project from the list.</p>
</li>
<li><p>Configure build settings if necessary (though for simple static sites, Netlify automatically detects them).</p>
</li>
</ol>
<h4 id="heading-4-click-deploy">4. <strong>Click "Deploy"</strong></h4>
<p>After connecting your repository, Netlify will display a "Deploy" button.</p>
<ol>
<li><p>Click "Deploy" to trigger the build and deployment process.</p>
</li>
<li><p>Netlify will pull your code from GitHub, build the site (if needed), and deploy it to a live URL.</p>
</li>
</ol>
<p>Your project is now live on the web, and you’ll be provided with a URL where you can access the deployed site.</p>
<h4 id="heading-5-access-the-deployed-url-and-append-the-css-file-url">5. <strong>Access the Deployed URL and Append the CSS File URL</strong></h4>
<p>You’ll access the deployed site by visiting the URL provided by Netlify and directly referencing the CSS file you uploaded.</p>
<ol>
<li><p>Once your site is deployed, note down the provided URL (for example, <a target="_blank" href="https://example.netlify.app"><code>https://example.netlify.app</code></a>).</p>
</li>
<li><p>To access a specific CSS file, append the file name to the URL, for example: <a target="_blank" href="https://example.netlify.app/styles.css"><code>https://example.netlify.app/styles.css</code></a>.</p>
</li>
<li><p>Here, <code>styles.css</code> is the name of your CSS file that you uploaded to GitHub and deployed via Netlify.</p>
</li>
</ol>
<p>This will allow you to view or reference the CSS file directly through a public URL.</p>
<p>This process essentially helps you host your project and its assets on Netlify, allowing easy access to any file (like <code>filename.css</code>) that you uploaded to GitHub. You can use these public links in your projects or share them.</p>
<p><strong>And that’s it! Link this URL to your project's CSS file.</strong></p>
<p>I have hosted the main CSS file on the Netlify app so that it can be accessed anywhere simply by importing it into your project. Here is the URL of my hosted CSS file: <code>https://hashnodeblogchallenge.netlify.app/index.css</code>.</p>
<p>The beauty of component libraries is that they allow you to focus on development rather than design.</p>
<h2 id="heading-faq">FAQ</h2>
<h3 id="heading-what-benefits-have-we-gained-from-this">What Benefits Have We Gained from This?</h3>
<p>Now, you simply need to copy the HTML code and import the CSS file into your project. Here are the key benefits:</p>
<ul>
<li><p><strong>Reduces time</strong> spent on repetitive CSS coding.</p>
</li>
<li><p>Provides <strong>greater control</strong> over components, allowing for customization based on your needs.</p>
</li>
<li><p>Offers <strong>real-time experience</strong> with HTML and CSS, enabling you to learn core concepts effectively.</p>
</li>
</ul>
<h3 id="heading-what-if-i-want-to-change-something">What if I Want to Change Something?</h3>
<p>This is straightforward. Just edit your CSS file and update the header colour from black to blue where you have declared that header class or ID.</p>
<h3 id="heading-what-if-i-want-to-create-more-components">What if I Want to Create More Components?</h3>
<p>You can create as many components as you need! Just store the style code in the same hosted CSS file, and everything will work seamlessly.</p>
<h3 id="heading-how-does-this-save-me-time">How Does This Save Me Time?</h3>
<p>Imagine you need to create 5 websites, each with 5 pages (that’s a total of 25 pages). If you identify common elements, such as headers and footers, that will be used across all 25 pages, you can avoid writing 25 separate components. Instead, you can simply use the components from your library—just copy and paste the HTML and add the CSS file.</p>
<h3 id="heading-what-lets-the-entire-app-function-with-just-one-line-of-css">What Lets the Entire App Function with Just One Line of CSS?</h3>
<p>The concept is quite simple and can be broken down into the following steps:</p>
<ol>
<li><p><strong>Create components</strong> based on your requirements.</p>
</li>
<li><p><strong>Control their design</strong> with CSS and apply the necessary properties.</p>
</li>
<li><p><strong>Host your main CSS file</strong> somewhere to obtain a new URL, which you can use to import your CSS styles in HTML.</p>
</li>
</ol>
<p><strong>Now you can calculate how much time you have saved.</strong></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Creating a component library using <strong>HTML</strong> and <strong>CSS</strong> allows you to build beautiful web pages quickly and effectively.</p>
<p>It also provides you with a deep understanding of HTML and CSS, which are essential skills for a successful software development career. With these skills, you'll be able to create engaging layouts without spending excessive time coding from scratch.</p>
<p>To help you get started, here’s an example of a component library I developed, which includes 10+ beautiful components: <a target="_blank" href="https://slateui.netlify.app">SlateUI</a>.</p>
<p>Now, you simply need to copy the HTML code and paste it where you want to display your components, along with importing your CSS file URL into that HTML file.</p>
<p>So guys this is the end from my side. If you find this article useful, then do share it and connect with me – I am open to opportunities:</p>
<ul>
<li><p>Follow Me on X: <a target="_blank" href="https://x.com/prankurpandeyy">Prankur's Twitter</a></p>
</li>
<li><p>Follow me on LinkedIn: <a target="_blank" href="https://linkedin.com/in/prankurpandeyy">Prankur's Linkedin</a></p>
</li>
<li><p>Look at my Portfolio here: <a target="_blank" href="https://prankurpandeyy.netlify.app/">Prankur's Portfolio</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What are Controlled and Uncontrolled Components in React.js? ]]>
                </title>
                <description>
                    <![CDATA[ In React.js, managing form inputs and user interactions is a crucial part of building dynamic web applications.  Two key concepts that developers need to understand are controlled and uncontrolled components. These concepts define how form data is ha... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-are-controlled-and-uncontrolled-components-in-react/</link>
                <guid isPermaLink="false">66c4c41fbd556981b1bdc443</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Fri, 21 Jun 2024 20:18:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In React.js, managing form inputs and user interactions is a crucial part of building dynamic web applications. </p>
<p>Two key concepts that developers need to understand are controlled and uncontrolled components. These concepts define how form data is handled within a React component. </p>
<p>Controlled components rely on React state to manage the form data, while uncontrolled components use the DOM itself to handle form data. </p>
<p>In this article, we will explore the differences between controlled and uncontrolled components, how to implement them, and some best practices for using each approach in your React applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-are-controlled-components">What are Controlled Components</a>?</li>
<li><a class="post-section-overview" href="#heading-how-controlled-components-work">How Controlled Components Work</a> </li>
<li><a class="post-section-overview" href="#heading-benefits-of-using-controlled-components">Benefits of using Controlled Components</a></li>
<li><a class="post-section-overview" href="#heading-examples-of-controlled-components">Examples of Controlled Components</a></li>
<li><a class="post-section-overview" href="#heading-what-are-uncontrolled-components">What are Uncontrolled Components</a>?</li>
<li><a class="post-section-overview" href="#heading-how-uncontrolled-components-work">How Uncontrolled Components Work</a></li>
<li><a class="post-section-overview" href="#heading-when-to-use-uncontrolled-components">When to use Uncontrolled Components</a></li>
<li><a class="post-section-overview" href="#heading-limitations-of-uncontrolled-components">Limitations to Uncontrolled Components</a></li>
<li><a class="post-section-overview" href="#heading-examples-of-uncontrolled-components">Examples of Uncontrolled Components</a></li>
<li><a class="post-section-overview" href="#heading-factors-to-consider-when-choosing-between-controlled-and-uncontrolled-components">Factors to Consider When Choosing Between Controlled and Uncontrolled Components</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-what-are-controlled-components">What are Controlled Components?</h2>
<p>Controlled components are form elements (like <code>input</code>, <code>textarea</code>, or <code>select</code>) that are managed by React state. This means that the value of the form element is set and updated through React state, making React the "single source of truth" for the form data. </p>
<p>By controlling form elements via state, you gain more control over user interactions and can easily enforce validation, format data, and respond to changes.</p>
<p>Here's an example of a controlled component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ControlledComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [value, setValue] = useState(<span class="hljs-string">''</span>);

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

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    alert(<span class="hljs-string">'A name was submitted: '</span> + value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Name:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ControlledComponent;
</code></pre>
<p>In this example:</p>
<ul>
<li>The <code>value</code> state holds the current value of the input field.</li>
<li>The <code>handleChange</code> function updates the state whenever the user types in the input field.</li>
<li>The <code>handleSubmit</code> function handles the form submission, using the current state value.</li>
</ul>
<h2 id="heading-how-controlled-components-work">How Controlled Components Work</h2>
<p>Controlled components in React ensure that the form data is handled by the React state, providing a consistent and predictable way to manage user input. </p>
<p>Here’s a breakdown of how these components work, including state management in the parent component, passing values as props to child components, handling user input with event handlers, and updating state in the parent component.</p>
<h3 id="heading-state-management-in-the-parent-component">State Management in the Parent Component</h3>
<p>State management is often handled in the parent component, especially when multiple child components need to interact or share state. The parent component maintains the state and passes it down to child components via props.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./ChildComponent'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ParentComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Controlled Component Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span> <span class="hljs-attr">setValue</span>=<span class="hljs-string">{setInputValue}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<h3 id="heading-passing-values-as-props-to-a-child-component">Passing Values as Props to a Child Component</h3>
<p>The parent component passes the state value and a state updater function to the child component as props. This allows the child component to display the current state and update it when needed.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ChildComponent</span>(<span class="hljs-params">{ value, setValue }</span>) </span>{
  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setValue(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Name:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<h3 id="heading-handling-user-input-with-event-handlers">Handling User Input with Event Handlers</h3>
<p>Event handlers are used to manage user input. When the user types into the input field, the <code>onChange</code> event triggers the <code>handleChange</code> function, which updates the state in the parent component.</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ChildComponent</span>(<span class="hljs-params">{ value, setValue }</span>) </span>{
  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setValue(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Name:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-updating-state-in-a-parent-component">Updating State in a Parent Component</h3>
<p>When the state updater function (<code>setValue</code>) is called in the child component, it updates the state in the parent component. This causes the parent component to re-render, which in turn re-renders the child component with the new state value.</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ParentComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Controlled Component Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span> <span class="hljs-attr">setValue</span>=<span class="hljs-string">{setInputValue}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-putting-it-all-together">Putting It All Together</h3>
<p>Here's the complete example showing how controlled components work with state management in the parent component:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ParentComponent.jsx</span>
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./ChildComponent'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ParentComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Controlled Component Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span> <span class="hljs-attr">setValue</span>=<span class="hljs-string">{setInputValue}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;

<span class="hljs-comment">// ChildComponent.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ChildComponent</span>(<span class="hljs-params">{ value, setValue }</span>) </span>{
  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setValue(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Name:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>Controlled components in React provide a good way to manage form data by using React state as the single source of truth. This approach involves managing state in the parent component, passing values and state updater functions as props to child components, handling user input with event handlers, and updating state in the parent component. </p>
<p>This method ensures consistent and predictable form behavior, making it easier to implement validation, conditional rendering, and other interactive features.</p>
<h2 id="heading-benefits-of-using-controlled-components">Benefits of Using Controlled Components</h2>
<p>Controlled components offer several advantages that can significantly improve the development experience and functionality of React applications. Here are the key benefits:</p>
<h3 id="heading-predictable-state-management">Predictable State Management</h3>
<p>Using controlled components ensures that the form data is always in sync with the React state. This predictability comes from having a single source of truth for the data, which is the state itself. </p>
<p>Since the state drives the UI, any change in the state immediately reflects in the form elements and vice versa. This makes it easier to debug and understand how data flows through your application.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PredictableForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current value: {name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In this example, the input field and the displayed text are always synchronized, providing a predictable behavior.</p>
<h3 id="heading-easier-form-validation">Easier Form Validation</h3>
<p>Controlled components make it straightforward to implement form validation. Since the form data is stored in the component state, you can easily validate it before updating the state or on form submission. This approach allows you to provide real-time feedback to users as they interact with the form.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ValidatedForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-string">''</span>);

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

    <span class="hljs-keyword">if</span> (!value.includes(<span class="hljs-string">'@'</span>)) {
      setError(<span class="hljs-string">'Invalid email address'</span>);
    } <span class="hljs-keyword">else</span> {
      setError(<span class="hljs-string">''</span>);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> '<span class="hljs-attr">red</span>' }}&gt;</span>{error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here, the validation logic runs on every change, providing immediate feedback to the user if the input is invalid.</p>
<h3 id="heading-integration-with-complex-ui-libraries">Integration with Complex UI Libraries</h3>
<p>Controlled components integrate seamlessly with complex UI libraries and frameworks, such as Redux for state management or Formik for handling forms. </p>
<p>By managing form data in the component state, you can easily connect your forms to these libraries and benefit from their advanced features like global state management, asynchronous data fetching, and more.</p>
<p><strong>Example with Formik:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Formik, Form, Field, ErrorMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">'formik'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Yup <span class="hljs-keyword">from</span> <span class="hljs-string">'yup'</span>;

<span class="hljs-keyword">const</span> SignupForm = <span class="hljs-function">() =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Formik</span>
    <span class="hljs-attr">initialValues</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">email:</span> '' }}
    <span class="hljs-attr">validationSchema</span>=<span class="hljs-string">{Yup.object({</span>
      <span class="hljs-attr">email:</span> <span class="hljs-attr">Yup.string</span>()<span class="hljs-attr">.email</span>('<span class="hljs-attr">Invalid</span> <span class="hljs-attr">email</span> <span class="hljs-attr">address</span>')<span class="hljs-attr">.required</span>('<span class="hljs-attr">Required</span>'),
    })}
    <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{(values,</span> { <span class="hljs-attr">setSubmitting</span> }) =&gt;</span> {
      setTimeout(() =&gt; {
        alert(JSON.stringify(values, null, 2));
        setSubmitting(false);
      }, 400);
    }}
  &gt;
    {({ isSubmitting }) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">Form</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Field</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ErrorMessage</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">"div"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{isSubmitting}</span>&gt;</span>
          Submit
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Form</span>&gt;</span>
    )}
  <span class="hljs-tag">&lt;/<span class="hljs-name">Formik</span>&gt;</span></span>
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SignupForm;
</code></pre>
<p>In this example, Formik handles form state and validation, demonstrating how controlled components can be part of more complex setups.</p>
<p>Controlled components provide predictable state management, easier form validation, and seamless integration with complex UI libraries. </p>
<p>By keeping the form data in the React state, you ensure consistency and control over your application's behavior, making it easier to build and maintain interactive and dynamic user interfaces.</p>
<h2 id="heading-examples-of-controlled-components">Examples of Controlled Components</h2>
<p>Controlled components are fundamental in React for handling form inputs in a predictable and manageable way. </p>
<p>Here are some examples of how you can implement controlled components for various types of form inputs, including text fields, email fields, password fields, select menus, checkboxes, and radio buttons.</p>
<h3 id="heading-input-fields-text-email-password">Input Fields (Text, Email, Password)</h3>
<h5 id="heading-text-input">Text Input</h5>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TextInput</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [text, setText] = useState(<span class="hljs-string">''</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Text:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{text}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Entered Text: {text}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TextInput;
</code></pre>
<h5 id="heading-email-input">Email Input</h5>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EmailInput</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Email:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Entered Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EmailInput;
</code></pre>
<h5 id="heading-password-input">Password Input</h5>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PasswordInput</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Password:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Entered Password: {password}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PasswordInput;
</code></pre>
<h4 id="heading-select-menus">Select Menus</h4>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SelectMenu</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [option, setOption] = useState(<span class="hljs-string">'option1'</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Choose an option:
        <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{option}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"option1"</span>&gt;</span>Option 1<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"option2"</span>&gt;</span>Option 2<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"option3"</span>&gt;</span>Option 3<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Selected Option: {option}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SelectMenu;
</code></pre>
<h4 id="heading-checkboxes">Checkboxes</h4>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Checkbox</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [isChecked, setIsChecked] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setIsChecked(event.target.checked);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Accept Terms:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">checked</span>=<span class="hljs-string">{isChecked}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Checked: {isChecked ? 'Yes' : 'No'}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Checkbox;
</code></pre>
<h4 id="heading-radio-buttons">Radio Buttons</h4>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RadioButton</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [selectedOption, setSelectedOption] = useState(<span class="hljs-string">'option1'</span>);

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">"option1"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{selectedOption</span> === <span class="hljs-string">'option1'</span>}
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
        /&gt;</span>
        Option 1
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">"option2"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{selectedOption</span> === <span class="hljs-string">'option2'</span>}
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
        /&gt;</span>
        Option 2
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"radio"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">"option3"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{selectedOption</span> === <span class="hljs-string">'option3'</span>}
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
        /&gt;</span>
        Option 3
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Selected Option: {selectedOption}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> RadioButton;
</code></pre>
<p>Controlled components provide a clear and consistent way to handle form inputs in React. By using React state to manage the values of input fields, select menus, checkboxes, and radio buttons, you ensure that the UI remains in sync with the state. </p>
<p>This approach simplifies validation, makes data handling predictable, and facilitates integration with complex UI libraries.</p>
<h2 id="heading-what-are-uncontrolled-components">What are Uncontrolled Components?</h2>
<p>Uncontrolled components in React manage their own state internally rather than relying on React state. This approach is useful for simple forms where you don't need to manipulate the input data through React state updates.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UncontrolledComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-comment">// Create a ref to hold the input DOM element</span>
    <span class="hljs-built_in">this</span>.inputRef = React.createRef();
  }

  handleSubmit = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Access the input value using the ref</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.inputRef.current.value);
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {/* Use ref attribute to attach the ref to the input element */}
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> 
          <span class="hljs-attr">ref</span>=<span class="hljs-string">{this.inputRef}</span> 
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handleSubmit}</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}
</code></pre>
<ul>
<li><strong>Ref Usage:</strong> In uncontrolled components, we use the <code>ref</code> attribute to create a reference (<code>this.inputRef</code>) to the DOM node of the input field.</li>
<li><strong>Handling Input:</strong> When the user enters data and clicks "Submit", <code>this.inputRef.current.value</code> allows us to directly access the current value of the input field without involving React state.</li>
<li><strong>Advantages:</strong> Uncontrolled components can be simpler and faster for basic form handling. They are often used when the form data is not needed in React state for any processing or validation.</li>
</ul>
<p><strong>Key Points:</strong></p>
<ul>
<li><strong>Internal State:</strong> Uncontrolled components manage their state internally with the help of refs, not with React state updates.</li>
<li><strong>Direct DOM Access:</strong> Accessing form data is done directly through DOM refs (<code>this.inputRef.current.value</code>).</li>
<li><strong>Simplicity:</strong> They are straightforward for simple forms where real-time validation or complex form interactions are not necessary.</li>
</ul>
<p>Uncontrolled components are handy in scenarios where you want a lightweight approach to handling form data without the overhead of managing state in React.</p>
<h2 id="heading-how-uncontrolled-components-work">How Uncontrolled Components Work</h2>
<p>Uncontrolled components manage their state internally using DOM refs (<code>useRef</code> hook in functional components or <code>React.createRef()</code> in class components) to access form element values directly. </p>
<p>Unlike controlled components, where form data is managed through React state and updated via <code>setState</code>, uncontrolled components bypass React's state management for handling form inputs.</p>
<h3 id="heading-direct-dom-access-with-useref-hook">Direct DOM Access with useRef Hook</h3>
<p>In functional components, the <code>useRef</code> hook allows us to create a mutable reference that persists across renders. We can use this ref to directly access DOM nodes, such as input fields.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UncontrolledComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> inputRef = useRef(<span class="hljs-literal">null</span>); <span class="hljs-comment">// Create a ref to hold the input DOM element</span>

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Access the input value using the ref</span>
    <span class="hljs-built_in">console</span>.log(inputRef.current.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UncontrolledComponent;
</code></pre>
<h3 id="heading-accessing-an-elements-value-on-submit">Accessing an Element's Value on Submit</h3>
<p>In the example above:</p>
<ul>
<li><strong>Creating a Ref:</strong> <code>const inputRef = useRef(null);</code> initializes a ref named <code>inputRef</code> to hold the reference to the input DOM element.</li>
<li><strong>Handling Submit:</strong> When the "Submit" button is clicked (<code>onClick={handleSubmit}</code>), the <code>handleSubmit</code> function retrieves the current value of the input field using <code>inputRef.current.value</code>.</li>
</ul>
<p><strong>Key Points:</strong></p>
<ul>
<li><strong>DOM Access:</strong> The <code>useRef</code> hook allows direct access to DOM elements, enabling us to interact with them without updating React state.</li>
<li><strong>Form Submission:</strong> On form submission (<code>onClick={handleSubmit}</code>), the function accesses the current value of the input field through <code>inputRef.current.value</code>.</li>
<li><strong>Simplicity:</strong> Uncontrolled components are straightforward for basic form handling scenarios where direct DOM manipulation suffices, avoiding the need for managing state updates in React.</li>
</ul>
<p>Using uncontrolled components with <code>useRef</code> is particularly useful for handling forms where real-time validation or complex interactions aren't necessary, focusing instead on simplicity and performance.</p>
<h2 id="heading-when-to-use-uncontrolled-components">When to Use Uncontrolled Components</h2>
<p>Uncontrolled components are ideal in specific scenarios where simplicity and direct DOM manipulation are advantageous over managing state with React. </p>
<p>Here are the key situations when using uncontrolled components is beneficial:</p>
<h3 id="heading-1-simple-forms-with-limited-interactions">1. Simple Forms with Limited Interactions</h3>
<p>Uncontrolled components shine in scenarios where:</p>
<ul>
<li><strong>The Forms Arent' That Complex:</strong> The form is straightforward with minimal input fields and does not require complex validation or dynamic updates based on other form inputs.</li>
<li><strong>Performance is Important:</strong> Directly accessing form values via DOM refs (<code>useRef</code> or <code>React.createRef()</code>) can be more performant than updating React state for each input change, especially in large forms.</li>
<li><strong>You want Simplicity:</strong> When you prefer a simpler implementation without managing state updates and re-renders for form inputs.</li>
</ul>
<h3 id="heading-2-focus-management-selecting-text">2. Focus Management (Selecting Text)</h3>
<p>In some cases, you might need to manage user interaction such as selecting text within an input field or programmatically focusing on a specific input without triggering React state updates unnecessarily. </p>
<p>Uncontrolled components allow you to:</p>
<ul>
<li><strong>Directly manipulate the DOM:</strong> Use DOM methods like <code>select()</code> on the input element directly via refs to manage focus or text selection.</li>
<li><strong>Handling focus and text selection directly with refs</strong>: This can be more efficient and straightforward compared to triggering state updates and managing focus state in React components.</li>
</ul>
<h4 id="heading-example-use-case">Example Use Case:</h4>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UncontrolledComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> inputRef = useRef(<span class="hljs-literal">null</span>); <span class="hljs-comment">// Create a ref to hold the input DOM element</span>

  <span class="hljs-keyword">const</span> handleFocus = <span class="hljs-function">() =&gt;</span> {
    inputRef.current.select(); <span class="hljs-comment">// Selects all text in the input field</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">"Initial Value"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleFocus}</span>&gt;</span>Select Text<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UncontrolledComponent;
</code></pre>
<p>In this example, clicking the "Select Text" button calls <code>inputRef.current.select()</code> to select all text within the input field directly, without involving React state updates. This is a simple yet effective use of uncontrolled components for managing focus and text selection.</p>
<h2 id="heading-limitations-of-uncontrolled-components">Limitations of Uncontrolled Components</h2>
<p>Using uncontrolled components in React can offer simplicity and performance benefits in certain scenarios, but they also come with limitations that are important to consider:</p>
<h3 id="heading-difficulty-in-form-validation">Difficulty in Form Validation:</h3>
<ul>
<li>Uncontrolled components can make form validation more challenging compared to controlled components. Since the form data is managed internally by the DOM rather than React state, validating and ensuring data consistency across multiple inputs can be complex.</li>
<li>Validation logic often involves accessing and checking each input's value directly through refs (<code>ref.current.value</code>). This approach can lead to more manual and error-prone validation code, especially in forms with complex validation requirements.</li>
</ul>
<h3 id="heading-less-predictable-state-management">Less Predictable State Management:</h3>
<ul>
<li>Uncontrolled components bypass React's state management, which can lead to less predictable state handling in complex applications. Changes in form data are not automatically synchronized with React's state updates or other component state, potentially leading to inconsistencies.</li>
<li>This lack of synchronization can make it challenging to maintain a single source of truth for form data across different components or when integrating with other state management solutions like Redux or Context API.</li>
</ul>
<h3 id="heading-limited-react-ecosystem-integration">Limited React Ecosystem Integration:</h3>
<ul>
<li>Uncontrolled components may not fully leverage React's ecosystem features, such as state persistence, time-travel debugging (with Redux), or seamless integration with third-party libraries designed for controlled components.</li>
<li>Components relying on React state benefit from these features, enhancing developer productivity and application maintainability.</li>
</ul>
<h2 id="heading-examples-of-uncontrolled-components">Examples of Uncontrolled Components</h2>
<p>Uncontrolled components in React are particularly useful for handling input fields and textarea elements where direct DOM manipulation suffices, and React state management isn't necessary. </p>
<p>Here are examples of how uncontrolled components can be applied:</p>
<h3 id="heading-1-input-fields-read-only-or-pre-filled-data">1. Input Fields (Read-only or Pre-filled Data)</h3>
<p>Uncontrolled components can be used when you need to display read-only or pre-filled data in an input field without managing its state in React.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UncontrolledInput</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> initialValue = <span class="hljs-string">'Hello, World!'</span>;
  <span class="hljs-keyword">const</span> inputRef = useRef(<span class="hljs-literal">null</span>); <span class="hljs-comment">// Create a ref to hold the input DOM element</span>

  <span class="hljs-keyword">const</span> handleFocus = <span class="hljs-function">() =&gt;</span> {
    inputRef.current.select(); <span class="hljs-comment">// Selects all text in the input field on focus</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* Using defaultValue for pre-filled data */}
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{initialValue}</span> <span class="hljs-attr">readOnly</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleFocus}</span>&gt;</span>Select Text<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UncontrolledInput;
</code></pre>
<p>In this example:</p>
<ul>
<li>The <code>defaultValue</code> attribute sets the initial value of the input field.</li>
<li><code>readOnly</code> attribute prevents users from editing the input field, making it read-only.</li>
<li><code>useRef</code> hook manages focus and selection of text within the input field using <code>inputRef.current</code>.</li>
</ul>
<h3 id="heading-2-textarea-elements">2. Textarea Elements</h3>
<p>Uncontrolled components are also applicable to textarea elements, especially when dealing with multiline text input where immediate state updates are not necessary.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UncontrolledTextarea</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> initialText = <span class="hljs-string">'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'</span>;
  <span class="hljs-keyword">const</span> textareaRef = useRef(<span class="hljs-literal">null</span>); <span class="hljs-comment">// Create a ref to hold the textarea DOM element</span>

  <span class="hljs-keyword">const</span> handleClear = <span class="hljs-function">() =&gt;</span> {
    textareaRef.current.value = <span class="hljs-string">''</span>; <span class="hljs-comment">// Clear textarea content directly</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* Using defaultValue for pre-filled content */}
      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{textareaRef}</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{initialText}</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">{4}</span> <span class="hljs-attr">cols</span>=<span class="hljs-string">{50}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClear}</span>&gt;</span>Clear Text<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UncontrolledTextarea;
</code></pre>
<p>In this example:</p>
<ul>
<li>The <code>defaultValue</code> attribute sets the initial content of the textarea.</li>
<li><code>useRef</code> hook manages direct manipulation of textarea content using <code>textareaRef.current</code>.</li>
<li><code>rows</code> and <code>cols</code> attributes define the dimensions of the textarea.</li>
</ul>
<p><strong>Key points:</strong></p>
<ul>
<li><strong>Direct DOM Access:</strong> Uncontrolled components leverage <code>useRef</code> to directly manipulate DOM elements for managing input fields and textarea content.</li>
<li><strong>Performance:</strong> Suitable for scenarios where real-time updates or complex state management aren't required, enhancing performance by avoiding unnecessary state updates.</li>
<li><strong>Simplicity:</strong> Provides a straightforward approach to handling form elements with default or read-only values, maintaining simplicity in component logic.</li>
</ul>
<p>These examples demonstrate how uncontrolled components can handle input fields and textarea elements effectively in React applications, focusing on simplicity and direct DOM manipulation for specific use cases.</p>
<h2 id="heading-factors-to-consider-when-choosing-between-controlled-and-uncontrolled-components">Factors to Consider When Choosing Between Controlled and Uncontrolled Components</h2>
<p>When deciding between controlled and uncontrolled components in React, several factors should be considered to determine which approach best suits your application's requirements. Here are key considerations for each factor:</p>
<h3 id="heading-1-complexity-of-form">1. Complexity of Form</h3>
<h4 id="heading-controlled-components">Controlled Components:</h4>
<ul>
<li><strong>Advantages:</strong> Suitable for complex forms where you need precise control over the form state and its interaction with other components.</li>
<li><strong>Usage:</strong> Use controlled components when form inputs depend on each other, require validation, or when you need to synchronize form state across multiple components or pages.</li>
</ul>
<h4 id="heading-uncontrolled-components">Uncontrolled Components:</h4>
<ul>
<li><strong>Advantages:</strong> Simplify implementation for basic forms with minimal interactivity or where direct DOM manipulation suffices.</li>
<li><strong>Usage:</strong> Ideal for simple forms without complex validation or when managing form state in React isn't necessary for your use case.</li>
</ul>
<h3 id="heading-2-need-for-form-validation">2. Need for Form Validation</h3>
<h4 id="heading-controlled-components-1">Controlled Components:</h4>
<ul>
<li><strong>Advantages:</strong> Easier integration with form validation libraries (for example, Formik, Yup) since form state is managed within React state.</li>
<li><strong>Usage:</strong> Use controlled components when implementing complex validation rules, such as conditional validation or asynchronous validation logic.</li>
</ul>
<h4 id="heading-uncontrolled-components-1">Uncontrolled Components:</h4>
<ul>
<li><strong>Challenges:</strong> Handling form validation can be more manual and less integrated, as form data is managed directly through DOM manipulation.</li>
<li><strong>Usage:</strong> Consider uncontrolled components for simple forms where validation requirements are minimal or where custom validation logic can be managed without relying heavily on React state updates.</li>
</ul>
<h3 id="heading-3-integration-with-external-libraries">3. Integration with External Libraries</h3>
<h4 id="heading-controlled-components-2">Controlled Components:</h4>
<ul>
<li><strong>Advantages:</strong> Seamlessly integrates with external state management solutions like Redux or React's Context API for managing global application state.</li>
<li><strong>Usage:</strong> Prefer controlled components when your application requires integration with third-party libraries or when leveraging advanced React ecosystem features (for example, time-travel debugging with Redux).</li>
</ul>
<h4 id="heading-uncontrolled-components-2">Uncontrolled Components:</h4>
<ul>
<li><strong>Considerations:</strong> May require additional effort to integrate with external libraries that assume controlled component behavior.</li>
<li><strong>Usage:</strong> Use uncontrolled components when external state management isn't necessary, focusing on lightweight implementation and minimizing dependencies.</li>
</ul>
<h3 id="heading-additional-considerations">Additional Considerations:</h3>
<h4 id="heading-performance">Performance:</h4>
<p>Controlled components may incur overhead due to frequent state updates, whereas uncontrolled components can offer better performance for simple forms by reducing re-renders.</p>
<h4 id="heading-developer-preference">Developer Preference:</h4>
<p>Consider team familiarity and preferences with React state management patterns when deciding between controlled and uncontrolled components.</p>
<h3 id="heading-summary">Summary:</h3>
<p><strong>Choose Controlled Components</strong> for complex forms, robust validation needs, and seamless integration with external state management and validation libraries.</p>
<p><strong>Opt for Uncontrolled Components</strong> for simpler forms, minimal validation requirements, and when direct DOM manipulation provides sufficient functionality without the need for managing form state in React.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The choice between controlled and uncontrolled components in React hinges on several critical factors that determine the optimal approach for form management within your application.</p>
<p>Ultimately, the decision should align with your project's specific needs, considering factors such as form complexity, validation requirements, integration with external libraries, and developer preferences. </p>
<p>By carefully assessing these factors, you can implement the most effective form handling strategy in React that balances functionality, performance, and ease of maintenance.</p>
<p>Connect with me on <a target="_blank" href="https://linkedin.com/in/joanayebola">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Rating Component with the React Compound Component Pattern ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever watched a captivating movie or used a fantastic product and wanted to share your experience? In today's world, feedback is critical, and ratings are like currency.  Rating systems are everywhere, from the classic star ratings on movie r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-rating-component-with-the-react-compound-component-pattern/</link>
                <guid isPermaLink="false">66bb8908a5fd14123a8b49f9</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2024 22:03:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Group-341.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever watched a captivating movie or used a fantastic product and wanted to share your experience? In today's world, feedback is critical, and ratings are like currency. </p>
<p>Rating systems are everywhere, from the classic star ratings on movie review websites to the ubiquitous thumbs up/down on streaming platforms. They guide our choices, shape our opinions, and ultimately influence the success of products and services.</p>
<p>In this article, we will create a movie-themed rating component using the Compound Component pattern in React. I'll guide you through structuring the component, managing its state, and designing an interactive user interface that captures the essence of rating.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>While this article is tailored to be as low-level as possible, having a base understanding of the React compound component pattern is beneficial. </p>
<p>If you don’t have any experience with it, don't worry – I've got you! Just head over to <a target="_blank" href="https://www.freecodecamp.org/news/build-a-dynamic-dropdown-component/">this compound component article</a> where I break it down more extensively. Other prerequisites include.</p>
<ul>
<li>Fundamentals of HTML, CSS, and Tailwind CSS</li>
<li>Fundamentals of JavaScript, React, and React Hooks.</li>
</ul>
<h2 id="heading-what-well-cover"><strong>What We'll Cover:</strong></h2>
<ol>
<li><a class="post-section-overview" href="#heading-understanding-rating-components">Understanding Rating Components</a><br>– <a class="post-section-overview" href="#heading-what-comprises-a-rating-component">What Comprises a Rating Component</a><br>– <a class="post-section-overview" href="#heading-advantages-of-rating-components">Advantages of Rating Component</a></li>
<li><a class="post-section-overview" href="#heading-regular-react-method-1">How to Build a Rating Componen</a>t                                                                                – <a class="post-section-overview" href="#heading-regular-react-method-1">Regular React Method</a><br>– <a class="post-section-overview" href="#heading-compound-component-method">Compound Component Method</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upgrade-the-rating-component">How to Upgrade Rating Component</a></li>
<li><a class="post-section-overview" href="#heading-and-just-for-fun">And just for fun</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-understanding-rating-components">Understanding Rating Components</h2>
<p>Rating components are an essential part of modern web applications, particularly in contexts where user feedback is critical. These components provide a user-friendly interface for people to express their opinions, often in a quantifiable manner.</p>
<h3 id="heading-what-comprises-a-rating-component">What Comprises a Rating Component?</h3>
<p>A rating component is a UI element that allows users to provide a rating, usually on a fixed scale. Here are the typical elements that make up a rating component:</p>
<ul>
<li><strong>Icons or Symbols</strong>: These are the visual representations of the rating scale. Common examples include stars, hearts, thumbs, or numerical values.</li>
<li><strong>Interactive States</strong>: These components often change appearance based on user interaction, such as hovering or clicking.</li>
<li><strong>Feedback Mechanism</strong>: Some rating components display immediate feedback, such as highlighting the selected icons or showing the rating value.</li>
<li><strong>Accessibility Features</strong>: Ensuring that the component is accessible to all users, including keyboard navigation and screen readers, is crucial.</li>
<li><strong>Custom Feedback</strong>: Some rating components include a text area allowing users to comment. This feedback helps clarify the reasons behind their ratings and enables them to raise any issues they encounter.</li>
</ul>
<h3 id="heading-advantages-of-rating-components">Advantages of Rating Components</h3>
<p>Rating components offer several benefits, both for users and developers:</p>
<ul>
<li><strong>User Engagement</strong>: They make it easy and enjoyable for users to provide feedback, which can increase engagement.</li>
<li><strong>Quantifiable Feedback</strong>: Ratings provide clear, quantifiable data that can be easily analyzed to gauge user satisfaction.</li>
<li><strong>Guiding Decisions</strong>: For other users, ratings help in making informed decisions about movies, products, services, and more.</li>
<li><strong>Improving Products</strong>: For businesses, ratings are invaluable for understanding user preferences and areas for improvement.</li>
</ul>
<h2 id="heading-how-to-build-a-rating-component">How to Build a Rating Component</h2>
<p>I've prepared a GitHub repository with starter files to speed things up. Simply clone <a target="_blank" href="https://github.com/Daiveedjay/Rating-Component">this repo</a> and install the dependencies.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Let-s-get-this-party-started.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Let's get this party started</em></p>
<p>In this section, we'll build a single rating component with regular React, and then rebuild it with the CC pattern.</p>
<h3 id="heading-regular-react-method">Regular React Method</h3>
<p>You’re probably wondering why we’re going through the hassle of first building the component without the component pattern.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/woah-peter-griffin.gif" alt="Image" width="600" height="400" loading="lazy">
<em>woah peter griffin</em></p>
<p>Well, while learning the component pattern, I struggled to fully wrap my head around the logic and ended up with a couple of bugs which could have been prevented with better understanding. </p>
<p>To help with this, I found that building a smaller version of the feature before fully implementing the CCP eventually sped up my development process.</p>
<p>To begin, create a <code>RatingComponent</code> and import it into your <code>App</code> component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> RatingComponent <span class="hljs-keyword">from</span> <span class="hljs-string">"./RatingComponent"</span>;
<span class="hljs-keyword">import</span> { Toaster } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hot-toast"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" bg-[#EAF2F8]  gap-4 min-h-[100dvh] flex justify-center items-center flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Toaster</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl "</span>&gt;</span>My Ratings Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RatingComponent</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>Then head over to your <code>RatingComponent</code> and add some basic boilerplate to create a standard rating UI.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FiStar } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-icons/fi"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RatingComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex bg-white items-center justify-between  border border-black rounded-md min-w-[600px]  p-2"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-2 text-base font-semibold"</span>&gt;</span>
        Intersteller <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-400 "</span>&gt;</span>(2014)<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 p-2"</span>&gt;</span>
        {Array.from({ length: 5 }).map((_, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FiStar</span>
              <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span>
              <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">{0}</span>
              <span class="hljs-attr">fill</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">gold</span>"}
              <span class="hljs-attr">cursor</span>=<span class="hljs-string">"pointer"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"star"</span>
            /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This makes your UI look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/1-Ratings-UI-created.png" alt="Image" width="600" height="400" loading="lazy">
<em>Ratings UI created</em></p>
<p>At the moment, your UI is static and has no way of changing the rating values. To add interactivity, create a state which holds the initial value of the rating.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [stars, setStarts] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>Then attach the setting handler to update the value of the stars when you click on a star.</p>
<pre><code class="lang-js">&lt;FiStar
    size={<span class="hljs-number">25</span>}
    strokeWidth={<span class="hljs-number">0</span>}
    fill={<span class="hljs-string">"gold"</span>}
    cursor=<span class="hljs-string">"pointer"</span>
    className=<span class="hljs-string">"star"</span>
    onClick={<span class="hljs-function">() =&gt;</span> setStarts(index + <span class="hljs-number">1</span>)}
 /&gt;
</code></pre>
<p><strong>Note</strong>: We’re adding 1 to the set value since arrays are zero-based.</p>
<p>To confirm the value of the star being set on click, add a dynamic fill value to each star.</p>
<pre><code class="lang-js"> &lt;FiStar
   size={<span class="hljs-number">25</span>}
   strokeWidth={<span class="hljs-number">0</span>}
   fill={index + <span class="hljs-number">1</span> &lt;= stars ? <span class="hljs-string">"gold"</span> : <span class="hljs-string">"#D6DBDF"</span>}
   cursor=<span class="hljs-string">"pointer"</span>
   className=<span class="hljs-string">"star"</span>
   onClick={<span class="hljs-function">() =&gt;</span> setStarts(index + <span class="hljs-number">1</span>)}
/&gt;
</code></pre>
<p>Which yields the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/testing-the-rating-component-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the rating component</em></p>
<p>To further improve the user feedback, we can convert the meaning of each star and display it to them.</p>
<p>Start by creating an array of labels and colours for the stars.</p>
<pre><code class="lang-js"> <span class="hljs-keyword">const</span> ratingData = [
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Poor"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E74C3C"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Bad"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E59866"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Okay"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#F7DC6F"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Good"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#76D7C4"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Great"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#229954"</span> },
  ];
</code></pre>
<p>Then apply this data to reflect whatever the current ratings are.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RatingComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [stars, setStarts] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> ratingData = [
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Poor"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E74C3C"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Bad"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E59866"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Okay"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#F7DC6F"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Good"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#76D7C4"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Great"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#229954"</span> },
  ];
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex bg-white items-center justify-between  border border-black rounded-md min-w-[600px]  p-2"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-2 text-base font-semibold"</span>&gt;</span>
        Intersteller <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-400 "</span>&gt;</span>(2014)<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 p-2"</span>&gt;</span>
        {Array.from({ length: 5 }).map((_, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FiStar</span>
              <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span>
              <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">{0}</span>
              <span class="hljs-attr">fill</span>=<span class="hljs-string">{index</span> + <span class="hljs-attr">1</span> &lt;= <span class="hljs-string">stars</span> ? "<span class="hljs-attr">gold</span>" <span class="hljs-attr">:</span> "#<span class="hljs-attr">D6DBDF</span>"}
              <span class="hljs-attr">cursor</span>=<span class="hljs-string">"pointer"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"star"</span>
              <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setStarts(index + 1)}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {stars &gt; 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold min-w-[60px] p-2"</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> <span class="hljs-attr">ratingData</span>[<span class="hljs-attr">stars</span> <span class="hljs-attr">-</span> <span class="hljs-attr">1</span>]?<span class="hljs-attr">.color</span> }}&gt;</span>
          {ratingData[stars - 1]?.label}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold text-gray-400"</span>&gt;</span>No ratings yet...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Which gives this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/testing-the-rating-component-with-label-cues.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the rating component with label cues</em></p>
<p>And ta-da! Your ratings component is fully functional and every user can effectively use it to drop an accurate review.</p>
<h3 id="heading-compound-component-method">Compound Component Method</h3>
<p>For this method, we’ll take it a step further and create multiple rating components, because if we’re not doing the most, what are we doing? 😌</p>
<p>Start by creating the context for the component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> RatingContext = createContext();

<span class="hljs-keyword">const</span> MultiRatingsComponent = <span class="hljs-function">(<span class="hljs-params">{
  children,
  ratingsData,

}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RatingContext.Provider</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">ratingsData</span>,
      }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RatingContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>Since we’re going to be working with multiple sets of data to create numerous rating components, the structure of the data being passed in would differ.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> multiRatings = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dark Knight"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2008</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Knives Out"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Serendipity"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2001</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dressmaker"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Grand Budapest Hotel"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
  ];
  <span class="hljs-keyword">const</span> [ratings, setRatings] = useState(multiRatings);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-[#EAF2F8] gap-4 min-h-[100vh] flex justify-center items-center flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Toaster</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>My Ratings Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent</span>
        <span class="hljs-attr">ratingsData</span>=<span class="hljs-string">{ratings}</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">MultiRatingsComponent</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>Next, flesh out the rest of the component required to make our UI look like the single component we created earlier.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> MultiRatingsComponent = <span class="hljs-function">(<span class="hljs-params">{
  children,
  ratingsData,

}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [userFeedback, setUserFeedback] = useState([]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RatingContext.Provider</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">ratingsData</span>,
      }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative "</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RatingContext.Provider</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> Label = <span class="hljs-function">(<span class="hljs-params">{ name, year }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col justify-center gap-1 text-base font-semibold min-w-[220px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{name}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" text-[12px]  text-[#AAB7B8]"</span>&gt;</span>{year}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> RatingsContainer = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { ratingsData, updateRating } = useContext(RatingContext);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"min-w-[600px] bg-white rounded-md flex flex-col"</span>&gt;</span>
      {ratingsData &amp;&amp;
        ratingsData.map((singleData, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center px-4 py-6 border-[#f7f8f9] gap-[75px] border-[0.5px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Label</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{singleData.name}</span> <span class="hljs-attr">year</span>=<span class="hljs-string">{singleData.year}</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 "</span>&gt;</span>
              {Array.from({ length: 5 }).map((_, starIndex) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">RatingIcon</span>
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{starIndex}</span>
                  <span class="hljs-attr">filled</span>=<span class="hljs-string">{starIndex</span> &lt; <span class="hljs-attr">singleData.rating</span>}
                /&gt;</span>
              ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">const</span> RatingIcon = <span class="hljs-function">(<span class="hljs-params">{ filled }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FiStar</span>
      <span class="hljs-attr">size</span>=<span class="hljs-string">{25}</span>
      <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">{0}</span>
      <span class="hljs-attr">fill</span>=<span class="hljs-string">{filled</span> ? "<span class="hljs-attr">gold</span>" <span class="hljs-attr">:</span> "#<span class="hljs-attr">AAB7B8</span>"}
      <span class="hljs-attr">cursor</span>=<span class="hljs-string">"pointer"</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">"star"</span>
    /&gt;</span></span>
  );
};
</code></pre>
<p>Then assign each component to its parent to form the compound component.</p>
<pre><code class="lang-js">MultiRatingsComponent.Label = Label;
MultiRatingsComponent.RatingsContainer = RatingsContainer;
MultiRatingsComponent.RatingIcon = RatingIcon;
</code></pre>
<p>To see your component UI, nest the <code>RatingsContainer</code> inside its parent (the <code>App</code> component).</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> multiRatings = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dark Knight"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2008</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Knives Out"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Serendipity"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2001</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dressmaker"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Grand Budapest Hotel"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
  ];

  <span class="hljs-keyword">const</span> [ratings, setRatings] = useState(multiRatings);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-[#EAF2F8] gap-4 min-h-[100vh] flex justify-center items-center flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Toaster</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>My Ratings Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent</span>
        <span class="hljs-attr">ratingsData</span>=<span class="hljs-string">{ratings}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent.RatingsContainer</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">MultiRatingsComponent</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>With that, your UI should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/2-Ratings-UI-with-CC-pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>Ratings UI with CC pattern</em></p>
<p>To add our previous functionality where we could set ratings, as well as show their meaning via labels, start by creating an update function in the <code>App</code> component.</p>
<pre><code class="lang-js">  <span class="hljs-keyword">const</span> updateRating = <span class="hljs-function">(<span class="hljs-params">index, newRating</span>) =&gt;</span> {
    setRatings(<span class="hljs-function">(<span class="hljs-params">prevRatings</span>) =&gt;</span>
      prevRatings.map(<span class="hljs-function">(<span class="hljs-params">r, i</span>) =&gt;</span> (i === index ? { ...r, <span class="hljs-attr">rating</span>: newRating } : r))
    );
    <span class="hljs-built_in">console</span>.log(ratings);
  };
</code></pre>
<p>This function uses the index of the clicked component to find the particular data, the modifies the rating property based on the star you click on.</p>
<p>To use it, pass it into the <code>MultiRatingsComponent</code> via props, then share it with all its children with its context.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> MultiRatingsComponent = <span class="hljs-function">(<span class="hljs-params">{
  children,
  ratingsData,
  updateRating,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [userFeedback, setUserFeedback] = useState([]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RatingContext.Provider</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">ratingsData</span>,
        <span class="hljs-attr">updateRating</span>,
      }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative "</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RatingContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>Then consume that context in <code>RatingsContainer</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> RatingsContainer = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { ratingsData, updateRating } = useContext(RatingContext);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"min-w-[600px] bg-white rounded-md flex flex-col"</span>&gt;</span>
      {ratingsData &amp;&amp;
        ratingsData.map((singleData, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center px-4 py-6 border-[#f7f8f9] gap-[75px] border-[0.5px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Label</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{singleData.name}</span> <span class="hljs-attr">year</span>=<span class="hljs-string">{singleData.year}</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 "</span>&gt;</span>
              {Array.from({ length: 5 }).map((_, starIndex) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">RatingIcon</span>
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{starIndex}</span>
                  <span class="hljs-attr">filled</span>=<span class="hljs-string">{starIndex</span> &lt; <span class="hljs-attr">singleData.rating</span>}
                    <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> updateRating(index, starIndex + 1)}
                /&gt;
              ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Just before you check the UI, create a <code>RatingsLabel</code> component to show the meaning of each star right next to each star.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> RatingLabel = <span class="hljs-function">(<span class="hljs-params">{ ratingValue }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> ratingLabel = [
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Poor"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E74C3C"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Bad"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#E59866"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Okay"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#F7DC6F"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Good"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#76D7C4"</span> },
    { <span class="hljs-attr">label</span>: <span class="hljs-string">"Great"</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#229954"</span> },
  ];
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {ratingValue &gt; 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold min-w-[60px] p-2"</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> <span class="hljs-attr">ratingLabel</span>[<span class="hljs-attr">ratingValue</span> <span class="hljs-attr">-</span> <span class="hljs-attr">1</span>]?<span class="hljs-attr">.color</span> }}&gt;</span>
          {ratingLabel[ratingValue - 1]?.label}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold text-gray-400"</span>&gt;</span>No ratings yet...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

MultiRatingsComponent.RatingLabel = RatingLabel;
</code></pre>
<p>And nest it in the <code>RatingsContainer</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> RatingsContainer = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { ratingsData, updateRating } = useContext(RatingContext);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"min-w-[600px] bg-white rounded-md flex flex-col"</span>&gt;</span>
      {ratingsData &amp;&amp;
        ratingsData.map((singleData, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center px-4 py-6 border-[#f7f8f9] gap-[75px] border-[0.5px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Label</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{singleData.name}</span> <span class="hljs-attr">year</span>=<span class="hljs-string">{singleData.year}</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 "</span>&gt;</span>
              {Array.from({ length: 5 }).map((_, starIndex) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">RatingIcon</span>
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{starIndex}</span>
                  <span class="hljs-attr">filled</span>=<span class="hljs-string">{starIndex</span> &lt; <span class="hljs-attr">singleData.rating</span>}
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> updateRating(index, starIndex + 1)}
                /&gt;
              ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">RatingLabel</span> <span class="hljs-attr">ratingValue</span>=<span class="hljs-string">{singleData.rating}</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Drumroll, please…</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/testing-the-rating-component-with-CC-pattern-and-label-cues.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the rating component with CC pattern and label cues</em></p>
<p>With this implementation, you can easily have multiple rating bars, and managing each state would be a breeze.</p>
<h2 id="heading-how-to-upgrade-the-rating-component">How to Upgrade the Rating Component</h2>
<p>Alas, there’s one functionality we haven't implemented. No great rating component is complete without a form which allows users to express their opinions past a couple of stars.</p>
<p>To create a comment component, create a form and some state to manage that form.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Comment = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [comment, setComment] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full mt-2 "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-2 text-base font-semibold "</span>&gt;</span>Comment<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative "</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{(e)</span>=&gt;</span> handleSubmit(e)}&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"comment"</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Add a review"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{comment}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setComment(e.target.value)}
          className="w-full p-4 rounded-md resize-none min-h-20"&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold absolute -bottom-1/2 right-0 border bg-[#5499C7] transition-all hover:bg-[#21618C] rounded-md py-2 px-4 text-white"</span>&gt;</span>
          Submit
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

MultiRatingsComponent.Comment = Comment;
</code></pre>
<p>Then create a handler function for that form.</p>
<pre><code class="lang-js">  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();

    <span class="hljs-keyword">if</span> (comment.length &lt; <span class="hljs-number">3</span>) {
      toast.error(<span class="hljs-string">"Please add more text"</span>);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Clear the comment input</span>
    setComment(<span class="hljs-string">""</span>);
  };
</code></pre>
<p>To see the comments after a user submits the form, create a state to hold those comments in the parent context.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> MultiRatingsComponent = <span class="hljs-function">(<span class="hljs-params">{
  children,
  ratingsData,
  updateRating,

}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [userFeedback, setUserFeedback] = useState([]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RatingContext.Provider</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">ratingsData</span>,
        <span class="hljs-attr">updateRating</span>,
        <span class="hljs-attr">userFeedback</span>,
        <span class="hljs-attr">setUserFeedback</span>,

      }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative "</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RatingContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>Then consume that context and store the submitted data in the parent context.</p>
<pre><code class="lang-js"> <span class="hljs-keyword">const</span> { userFeedback, setUserFeedback,} =
    useContext(RatingContext);

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

    <span class="hljs-keyword">if</span> (comment.length &lt; <span class="hljs-number">3</span>) {
      toast.error(<span class="hljs-string">"Please add more text"</span>);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Create a new feedback object</span>
    <span class="hljs-keyword">const</span> newFeedback = { comment };

    <span class="hljs-comment">// Update the userFeedback state</span>
    setUserFeedback([...userFeedback, newFeedback]);

    <span class="hljs-comment">// Clear the comment input</span>
    setComment(<span class="hljs-string">""</span>);
  };
</code></pre>
<p>To view all the comments left by users, create a <code>UserFeedback</code> component like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> UserFeedback = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { userFeedback } = useContext(RatingContext);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"absolute top-0 px-8 py-2 translate-x-full bg-white rounded-md max-w-[300px] -right-5"</span>&gt;</span>
      {userFeedback.length &gt; 0 ? (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-2 text-xl font-semibold"</span>&gt;</span>
            Here are what user think
          <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            {userFeedback.map((user, index) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"px-2 "</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>
                  {index + 1}.{" "}
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold "</span>&gt;</span>{user.name} <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> --{" "}
                  {user.text}
                <span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      ) : (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold ext-xl"</span>&gt;</span>No user feedback yet...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
      )}
    &lt;/div&gt;
  );
};
MultiRatingsComponent.UserFeedback = UserFeedback;
</code></pre>
<p>This component consumes the state holding the user comments and displays them on the screen.</p>
<p>Just before we test it out, I wanted to replicate a fun quirk I notice from Google whenever someone views your docs. They assign a random name to each user and so will we.</p>
<p>Head over to your <code>App</code> component and create this array:</p>
<pre><code class="lang-js"> <span class="hljs-keyword">const</span> randomNames = [
    <span class="hljs-string">"Anonymous Llama"</span>,
    <span class="hljs-string">"Mysterious Moose"</span>,
    <span class="hljs-string">"Stealthy Sloth"</span>,
    <span class="hljs-string">"Phantom Panda"</span>,
    <span class="hljs-string">"Incognito Iguana"</span>,
    <span class="hljs-string">"Unknown Unicorn"</span>,
    <span class="hljs-string">"Enigmatic Elephant"</span>,
    <span class="hljs-string">"Ghostly Giraffe"</span>,
    <span class="hljs-string">"Shadowy Shark"</span>,
    <span class="hljs-string">"Cryptic Cobra"</span>,
    <span class="hljs-string">"Silent Swan"</span>,
    <span class="hljs-string">"Nameless Narwhal"</span>,
    <span class="hljs-string">"Obscure Octopus"</span>,
    <span class="hljs-string">"Unseen Uakari"</span>,
    <span class="hljs-string">"Hidden Hedgehog"</span>,
    <span class="hljs-string">"Masked Macaw"</span>,
    <span class="hljs-string">"Veiled Vulture"</span>,
    <span class="hljs-string">"Concealed Chameleon"</span>,
    <span class="hljs-string">"Covert Cockatoo"</span>,
    <span class="hljs-string">"Invisible Impala"</span>,
  ];
</code></pre>
<p>Then pass it into your <code>MultiRatingsComponent</code> via props.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> MultiRatingsComponent = <span class="hljs-function">(<span class="hljs-params">{
  children,
  ratingsData,
  updateRating,
  randomNames,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [userFeedback, setUserFeedback] = useState([]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RatingContext.Provider</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">ratingsData</span>,
        <span class="hljs-attr">updateRating</span>,
        <span class="hljs-attr">userFeedback</span>,
        <span class="hljs-attr">setUserFeedback</span>,
        <span class="hljs-attr">randomNames</span>,
      }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative "</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">RatingContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>Finally, modify your form handler function to send a random name with the comment.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Comment = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [comment, setComment] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> { userFeedback, setUserFeedback, randomNames } =
    useContext(RatingContext);

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

    <span class="hljs-keyword">if</span> (comment.length &lt; <span class="hljs-number">3</span>) {
      toast.error(<span class="hljs-string">"Please add more text"</span>);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Generate a random name between 1 and the length of the array</span>
    <span class="hljs-keyword">const</span> randomName =
      randomNames[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * randomNames.length)];

    <span class="hljs-comment">// Create a new feedback object</span>
    <span class="hljs-keyword">const</span> newFeedback = { <span class="hljs-attr">name</span>: randomName, comment };

    <span class="hljs-comment">// Update the userFeedback state</span>
    setUserFeedback([...userFeedback, newFeedback]);

    <span class="hljs-comment">// Clear the comment input</span>
    setComment(<span class="hljs-string">""</span>);
  };
</code></pre>
<p>Finally, render the <code>Comment</code> and <code>UserFeedback</code> components in their parent inside the <code>App</code> component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> multiRatings = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dark Knight"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2008</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Knives Out"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Serendipity"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2001</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Dressmaker"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"The Grand Budapest Hotel"</span>, <span class="hljs-attr">year</span>: <span class="hljs-number">2015</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> },
  ];

  <span class="hljs-keyword">const</span> randomNames = [...];

  <span class="hljs-keyword">const</span> [ratings, setRatings] = useState(multiRatings);

  <span class="hljs-keyword">const</span> updateRating = <span class="hljs-function">(<span class="hljs-params">index, newRating</span>) =&gt;</span> {
    setRatings(<span class="hljs-function">(<span class="hljs-params">prevRatings</span>) =&gt;</span>
      prevRatings.map(<span class="hljs-function">(<span class="hljs-params">r, i</span>) =&gt;</span> (i === index ? { ...r, <span class="hljs-attr">rating</span>: newRating } : r))
    );
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-[#EAF2F8] gap-4 min-h-[100vh] flex justify-center items-center flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Toaster</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>My Ratings Component<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent</span>
        <span class="hljs-attr">ratingsData</span>=<span class="hljs-string">{ratings}</span>
        <span class="hljs-attr">updateRating</span>=<span class="hljs-string">{updateRating}</span>
        <span class="hljs-attr">randomNames</span>=<span class="hljs-string">{randomNames}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent.RatingsContainer</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent.Comment</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MultiRatingsComponent.UserFeedback</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">MultiRatingsComponent</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>And…Presto!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/testing-the-rating-component-with-CC-pattern--label-cues-and-comments.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the rating component with CC pattern, label cues and comments</em></p>
<p>Your rating component is completed, with the added functionality of comments. ⭐<br>How would you rate the ride throughout this build? 5 stars? 😉</p>
<h3 id="heading-additional-information">Additional Information</h3>
<p>Here are links to all the resources you may need from this article.</p>
<ul>
<li><a target="_blank" href="https://github.com/Daiveedjay/Rating-Component">Starter files</a></li>
<li><a target="_blank" href="https://github.com/Daiveedjay/Rating-Component/tree/Single-Rating-Component">Regular React Pattern</a></li>
<li><a target="_blank" href="https://github.com/Daiveedjay/Rating-Component/tree/Compound-Component-Rating">Compound Component Pattern</a></li>
</ul>
<h3 id="heading-and-just-for-fun">And just for fun...</h3>
<p>Since we built a rating component centered around movies, here are 5 movies I consider to be worth 5 stars in no particular order.</p>
<ul>
<li><a target="_blank" href="https://www.google.com/search?q=The+Grand+Budapest+Hotel&amp;oq=The+Grand+Budapest+Hotel&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiPAjIHCAIQABiPAjIGCAMQRRhA0gEHMzUyajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8">The Grand Budapest Hotel</a> (Comedy/Crime)</li>
<li><a target="_blank" href="https://www.google.com/search?gs_ssp=eJzj4tVP1zc0TDLPNi5JKzE2YPSSKslIVchNTM_LTMtMTs0rUShOLUvNUzAyMDQDACXhDZw&amp;q=the+magnificent+seven+2016&amp;oq=the+magnifi&amp;gs_lcrp=EgZjaHJvbWUqDAgCEC4YQxiABBiKBTIGCAAQRRg5MgoIARAuGNQCGIAEMgwIAhAuGEMYgAQYigUyBwgDEAAYgAQyBwgEEC4YgAQyCggFEC4Y1AIYgAQyCggGEC4Y1AIYgAQyBwgHEAAYgAQyBwgIEC4YgAQyBwgJEAAYjwLSAQg0NjQxajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8">The Magnificent Seven</a> (Western/Action)</li>
<li><a target="_blank" href="https://www.google.com/search?q=django+unchained&amp;sca_esv=616ade3b683ed7c0&amp;sxsrf=ADLYWIK4xUiB8xs1iwXWvE9LfHZsNyCFsg%3A1717326804304&amp;ei=1FNcZqaeEtqyhbIPzYCtwQU&amp;gs_ssp=eJzj4tLP1TdIL88qN0g2YPQSSMlKzEvPVyjNS85IzMxLTQEAlJcKLw&amp;oq=django&amp;gs_lp=Egxnd3Mtd2l6LXNlcnAiBmRqYW5nbyoCCAAyDRAuGIAEGLEDGEMYigUyChAAGIAEGEMYigUyChAuGIAEGEMYigUyDRAAGIAEGLEDGEMYigUyChAAGIAEGEMYigUyChAuGIAEGEMYigUyChAAGIAEGEMYigUyChAAGIAEGBQYhwIyBRAAGIAEMgUQABiABDIoEC4YgAQYsQMYQxiKBRiXBRjcBBjeBBjgBBj0AxjxAxj1Axj2A9gBA0jCHlDHBFiUEXACeAGQAQCYAZgCoAH0C6oBAzItNrgBAcgBAPgBAZgCCKACtwyoAhHCAgoQABiwAxjWBBhHwgINEAAYgAQYsAMYQxiKBcICDhAAGLADGOQCGNYE2AEBwgITEC4YgAQYsAMYQxjIAxiKBdgBAsICBxAjGCcY6gLCAhYQLhiABBhDGLQCGMgDGIoFGOoC2AECwgIKECMYgAQYJxiKBcICBBAjGCfCAhAQLhiABBixAxhDGIMBGIoFwgIIEAAYgAQYsQPCAgQQABgDwgILEAAYgAQYsQMYgwHCAiUQLhiABBhDGIoFGJcFGNwEGN4EGOAEGPQDGPEDGPUDGPYD2AEDwgIFEC4YgATCAigQLhiABBixAxhDGIoFGJcFGNwEGN4EGOAEGPQDGPEDGPUDGPYD2AEDmAMJiAYBkAYTugYGCAEQARgJugYGCAIQARgIugYGCAMQARgUkgcFMi4wLjagB72FAQ&amp;sclient=gws-wiz-serp">Django Unchained</a> (Western/Action)</li>
<li><a target="_blank" href="https://www.google.com/search?q=ford+vs+ferrari&amp;sca_esv=616ade3b683ed7c0&amp;sxsrf=ADLYWIL6hL7o3cnMX0eikkhJDvlhvLACHg%3A1717327001772&amp;ei=mVRcZpjqLr6whbIP-eS7kAw&amp;gs_ssp=eJzj4tVP1zc0TDOrNC5IK6o0YPTiT8svSlEoK1ZISy0qSizKBACjAwqR&amp;oq=ford+vs+fer&amp;gs_lp=Egxnd3Mtd2l6LXNlcnAiC2ZvcmQgdnMgZmVyKgIIADINEC4YgAQYsQMYQxiKBTIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBRAAGIAEMgUQABiABDIoEC4YgAQYsQMYQxiKBRiXBRjcBBjeBBjgBBj0AxjxAxj1Axj2A9gBA0jnMFCGA1jZJHAEeAGQAQCYAY8CoAHRF6oBBjAuMi4xMbgBAcgBAPgBAZgCEqACuiSoAhLCAgoQABiwAxjWBBhHwgINEAAYgAQYsAMYQxiKBcICDhAAGLADGOQCGNYE2AEBwgITEC4YgAQYsAMYQxjIAxiKBdgBAsICBxAjGCcY6gLCAhYQLhiABBhDGLQCGMgDGIoFGOoC2AECwgIZEC4YgAQYQxjUAhi0AhjIAxiKBRjqAtgBAsICChAjGIAEGCcYigXCAgQQIxgnwgIKEC4YgAQYQxiKBcICERAuGIAEGLEDGNEDGIMBGMcBwgIIEAAYgAQYsQPCAgsQABiABBixAxiDAcICChAAGIAEGEMYigXCAhAQABiABBixAxhDGIMBGIoFwgIrEC4YgAQYsQMYQxiKBRiXBRjcBBjeBBjgBBj0AxjxAxj1Axj2Axj3A9gBA8ICDRAAGIAEGLEDGEMYigXCAhAQABiABBixAxhDGMkDGIoFwgILEAAYgAQYkgMYigXCAgoQABiABBgUGIcCmAMKiAYBkAYTugYGCAEQARgJugYGCAIQARgIugYGCAMQARgUkgcKNC4wLjEzLjctMaAH3qsB&amp;sclient=gws-wiz-serp">Ford vs Ferrari</a> (Sports/Action)</li>
<li><a target="_blank" href="https://www.imdb.com/title/tt1375666/">Inception</a> (Action/Sci-fi)</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, crafting a movie-themed rating component using the Compound Component pattern in React is a surefire blockbuster for your projects. This approach enables you to create a sleek, modular, and maintainable codebase. </p>
<p>Mastering this technique ensures your rating system is both functional and ready for the future. Lights, camera, action – may your coding journey dazzle with five-star reviews and standing ovations!</p>
<h3 id="heading-like-my-articles">Like my articles?</h3>
<p>Feel free to <a target="_blank" href="https://www.buymeacoffee.com/JajaDavid">buy me a coffee here</a>, to keep my brain chugging and provide more articles like this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/coffee-tom.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Coffee Tom</em></p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Function Components vs Class Components in React – With Examples ]]>
                </title>
                <description>
                    <![CDATA[ In React, there are two primary ways to create components: function and class components. Each has its own syntax and use cases, although with the introduction of React Hooks, the gap between them has narrowed significantly. But the selection of appr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/function-component-vs-class-component-in-react/</link>
                <guid isPermaLink="false">66c4c3ce8e05d0e4345147c3</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Tue, 16 Apr 2024 22:37:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--5-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In React, there are two primary ways to create components: function and class components. Each has its own syntax and use cases, although with the introduction of React Hooks, the gap between them has narrowed significantly. But the selection of appropriate component types is still very crucial for building efficient and maintainable React applications.</p>
<p>In this article, we'll explore the foundational differences between function and class components, providing a clear understanding of their strengths and ideal use cases. </p>
<p>By understanding these concepts, developers can make informed decisions when constructing React components, ultimately enhancing the structure and functionality of their web applications.</p>
<h2 id="heading-what-are-react-components">What are React Components?</h2>
<p>In React, components are the building blocks of a user interface. They are reusable, self-contained pieces of code that represent a part of the UI. React allows you to break down your UI into smaller components, which makes it easier to manage and maintain your codebase.</p>
<p>You can think of components as custom HTML elements that encapsulate their own logic and UI structure. They can accept inputs called props (short for properties) and return React elements describing what should appear on the screen.</p>
<p>There are two main types of components in React:</p>
<p><strong>Function Components:</strong> These are simple JavaScript functions that take props as input and return JSX elements. They are often used for presentational or stateless components.</p>
<p><strong>Class Components:</strong> These are ES6 classes that extend from <code>React.Component</code> or <code>React.PureComponent</code>. They have a <code>render()</code> method where you define the structure of your component's UI using JSX. Class components are used for components that need to manage state or have lifecycle methods.</p>
<p>With the introduction of React Hooks, function components gained the ability to manage state and use lifecycle methods, blurring the distinction between function and class components. However, both types of components are still widely used in React applications.</p>
<h2 id="heading-function-vs-class-components-a-high-level-overview">Function vs Class Components: A High-Level Overview</h2>
<h3 id="heading-function-components">Function Components</h3>
<p><strong>Syntax:</strong> Function components are defined using the <code>function</code> keyword or arrow function syntax.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Function component using function keyword</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FunctionComponent</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, {props.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a function component.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Function component using arrow function syntax</span>
<span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, {props.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a function component.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</code></pre>
<p>In the code snippet above, both examples define a function component called <code>FunctionComponent</code> that takes <code>props</code> as input and returns JSX elements. The component simply renders a greeting message along with some text. </p>
<p>The first example uses the <code>function</code> keyword to define the function component, while the second example uses arrow function syntax. Both syntaxes are valid and achieve the same result.</p>
<p><strong>State Management:</strong> Traditionally, function components were stateless and couldn't hold their own state. However, with the introduction of React Hooks (like <code>useState</code>), function components can now manage state using Hooks.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Using useState Hook to manage state</span>
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</code></pre>
<p>In this example, we use the <code>useState</code> Hook to initialize a state variable <code>count</code> with an initial value of <code>0</code>. The <code>useState</code> Hook returns an array with two elements: the current state value (<code>count</code>) and a function (<code>setCount</code>) to update the state. </p>
<p>When the button is clicked, <code>setCount</code> is called with the new value of <code>count</code>, triggering a re-render with the updated state value displayed. This demonstrates how function components can now hold and manage their own state using React Hooks, making them more powerful and versatile.</p>
<p><strong>Lifecycle Methods:</strong> Function components don't have lifecycle methods. However, with React Hooks, you can use the <code>useEffect</code> Hook to replicate lifecycle behavior (like <code>componentDidMount</code>, <code>componentDidUpdate</code>, <code>componentWillUnmount</code>, and so on).</p>
<p>Let's discuss some of the most commonly used lifecycle methods:</p>
<p><strong>componentDidMount:</strong> This method is invoked immediately after a component is mounted (that is, inserted into the DOM tree). It is commonly used to perform initial setup, such as fetching data from an API or setting up event listeners.</p>
<p><strong>componentDidUpdate:</strong> This method is invoked immediately after updating occurs. It is triggered whenever the component's props or state changes. It is commonly used to perform actions based on the updated state or props, such as making additional API calls.</p>
<p><strong>componentWillUnmount:</strong> This method is invoked immediately before a component is unmounted and destroyed. It is commonly used to perform cleanup, such as removing event listeners or cancelling any ongoing tasks.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

  <span class="hljs-comment">// useEffect Hook to replicate componentDidMount and componentDidUpdate</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// This code block runs after every render</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Component did mount or update"</span>);

    <span class="hljs-comment">// Clean-up function (replicating componentWillUnmount)</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Component will unmount"</span>);
    };
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</code></pre>
<p>In this example, the <code>useEffect</code> Hook is used without a dependency array. This means the effect will run after every render, effectively replicating both <code>componentDidMount</code> and <code>componentDidUpdate</code> behavior. Inside the effect, you can perform any cleanup necessary, such as unsubscribing from subscriptions or removing event listeners, by returning a cleanup function. This cleanup function will be executed when the component unmounts, effectively replicating the <code>componentWillUnmount</code> behavior.</p>
<p>By leveraging the <code>useEffect</code> Hook, function components can now achieve the same lifecycle behavior as class components, further blurring the distinction between the two component types.</p>
<p><strong>Readability:</strong> Function components are generally more concise and easier to read, especially for simpler components.</p>
<h3 id="heading-class-components">Class Components</h3>
<p><strong>Syntax:</strong> Class components are ES6 classes that extend from <code>React.Component</code> or <code>React.PureComponent</code>. They have a <code>render()</code> method where you define the structure of your component's UI using JSX.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Define a class component that extends React.Component or React.PureComponent</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-comment">// Define constructor if necessary</span>
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-comment">// Initialize state if needed</span>
    <span class="hljs-built_in">this</span>.state = {
      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>
    };
  }

  <span class="hljs-comment">// Define lifecycle methods if necessary</span>
  componentDidMount() {
    <span class="hljs-comment">// Code to run after the component is mounted</span>
  }

  <span class="hljs-comment">// Define instance methods if necessary</span>
  handleClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Update state or perform other logic</span>
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count + <span class="hljs-number">1</span> });
  }

  <span class="hljs-comment">// Define render() method to return JSX</span>
  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {this.state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handleClick}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ClassComponent;
</code></pre>
<p>In this example:</p>
<ul>
<li>We imported <code>React</code> and <code>Component</code> from the 'react' package.</li>
<li>We defined a class component named <code>ClassComponent</code> that extends <code>Component</code>.</li>
<li>Inside the class component, we can define a constructor to initialize state or bind event handlers if necessary.</li>
<li>We can define lifecycle methods such as <code>componentDidMount</code>, <code>componentDidUpdate</code>, and so on, to hook into different stages of the component's lifecycle.</li>
<li>We defined the <code>render()</code> method, which returns JSX to describe the structure of the component's UI.</li>
<li>Any instance methods, event handlers, or other logic can be defined within the class.</li>
</ul>
<p><strong>State Management:</strong> Class components can hold and manage local state using the <code>this.state</code> property. They can also update state using <code>this.setState()</code>.</p>
<p>Let's illustrate this with a simple example:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-comment">// Initialize state</span>
    <span class="hljs-built_in">this</span>.state = {
      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>
    };
  }

  <span class="hljs-comment">// Define a method to update state</span>
  incrementCount = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Use this.setState() to update state</span>
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count + <span class="hljs-number">1</span> });
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {this.state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.incrementCount}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ClassComponent;
</code></pre>
<p>In this example:</p>
<ul>
<li>We initialized the component's state in the constructor using <code>this.state</code>.</li>
<li>The <code>incrementCount</code> method was defined within the class to update the <code>count</code> state. Inside this method, we called <code>this.setState()</code> and passed an object containing the new state or a function that returns the new state. React will merge the new state with the existing state.</li>
<li>In the <code>render()</code> method, we accessed the <code>count</code> state using <code>this.state.count</code> and displayed it within the JSX.</li>
<li>When the button is clicked, the <code>incrementCount</code> method is called, which updates the <code>count</code> state and triggers a re-render of the component.</li>
</ul>
<p>This demonstrates how class components in React can manage local state and update it using <code>this.setState()</code>. </p>
<p><strong>Lifecycle Methods:</strong> Class components have access to various lifecycle methods like <code>componentDidMount</code>, <code>componentDidUpdate</code>, and <code>componentWillUnmount</code>, which allow you to hook into different stages of a component's lifecycle.</p>
<p>Here's an example demonstrating the usage of these lifecycle methods in a class component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = {
      <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>
    };
  }

  componentDidMount() {
    <span class="hljs-comment">// Fetch initial data when the component mounts</span>
    <span class="hljs-built_in">this</span>.fetchData();
  }

  componentDidUpdate(prevProps, prevState) {
    <span class="hljs-comment">// Check if the data has changed</span>
    <span class="hljs-keyword">if</span> (prevState.data !== <span class="hljs-built_in">this</span>.state.data) {
      <span class="hljs-comment">// Data has changed, perform additional actions</span>
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Data has been updated:'</span>, <span class="hljs-built_in">this</span>.state.data);
    }
  }

  componentWillUnmount() {
    <span class="hljs-comment">// Cleanup tasks before the component is unmounted</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Component will unmount'</span>);
    <span class="hljs-comment">// For example, remove event listeners, cancel ongoing tasks, etc.</span>
  }

  fetchData() {
    <span class="hljs-comment">// Simulate fetching data from an API</span>
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">data</span>: <span class="hljs-string">'Some data fetched from API'</span> });
    }, <span class="hljs-number">1000</span>);
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Data: {this.state.data}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ClassComponent;
</code></pre>
<p>In this example:</p>
<ul>
<li><code>componentDidMount</code> is used to fetch initial data when the component mounts.</li>
<li><code>componentDidUpdate</code> is used to log a message whenever the data state changes.</li>
<li><code>componentWillUnmount</code> is used to log a message before the component is unmounted.</li>
</ul>
<p>These lifecycle methods provide hooks into different stages of a component's lifecycle, allowing you to perform setup, update, and cleanup tasks as needed. </p>
<p><strong>Instance Methods:</strong> You can define custom methods directly on the class, which can be helpful for organizing your component's logic.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = {
      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>
    };
  }

  <span class="hljs-comment">// Custom method to handle incrementing count</span>
  handleIncrement = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count + <span class="hljs-number">1</span> });
  }

  <span class="hljs-comment">// Custom method to handle decrementing count</span>
  handleDecrement = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count - <span class="hljs-number">1</span> });
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {this.state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handleIncrement}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handleDecrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ClassComponent;
</code></pre>
<p>In this example:</p>
<ul>
<li>We defined two custom instance methods <code>handleIncrement</code> and <code>handleDecrement</code> within the class component. These methods were defined using arrow function syntax to ensure they have access to the correct <code>this</code> context.</li>
<li>The <code>handleIncrement</code> method updates the <code>count</code> state by incrementing it by 1 when called.</li>
<li>The <code>handleDecrement</code> method updates the <code>count</code> state by decrementing it by 1 when called.</li>
<li>These custom methods are then used as event handlers for the buttons in the JSX returned by the <code>render</code> method.</li>
</ul>
<p>Defining custom instance methods in class components helps in organizing the component's logic, making it more readable and maintainable. Additionally, these methods can be reused across different parts of the component, enhancing code reusability. </p>
<p>It is important to note that, with the introduction of React Hooks, many tasks traditionally handled by class components can now be accomplished using function components. </p>
<p>Hooks such as <code>useState</code>, <code>useEffect</code>, <code>useContext</code>, and others provide a simpler and more concise way to manage state, handle side effects, and share logic across components. This shift towards Hooks empowers developers to write more function and modular code, reducing the reliance on class components. </p>
<p>While class components still have their place, especially in legacy codebases, the versatility and flexibility of Hooks make function components the preferred choice for building modern React applications.</p>
<h2 id="heading-advantages-of-function-component">Advantages of Function Component</h2>
<p><strong>Simpler Syntax:</strong> Function components have a simpler syntax compared to class components. They are essentially just JavaScript functions that take props as input and return React elements. This simplicity makes them easier to read and understand, especially for beginners.</p>
<p><strong>Pure Functions:</strong> Function components are essentially pure functions, meaning they only depend on their input (props) to produce output (UI). They don't have internal state or side effects, which makes them easier to reason about and test. This purity also helps improve performance, as React can optimize the rendering process more effectively.</p>
<p><strong>Reusability:</strong> Function components promote reusability by encapsulating UI logic within small, composable functions. Since they are just JavaScript functions, they can be easily reused in multiple parts of your application, leading to more modular and maintainable code.</p>
<p><strong>Using Props in Function Components:</strong> Function components make extensive use of props to pass data from parent to child components. This props-based approach promotes a clear and predictable data flow within your application, making it easier to understand how data is passed and used throughout your component hierarchy.</p>
<h2 id="heading-advantages-of-class-components">Advantages of Class Components</h2>
<p><strong>Explicit State Management:</strong> Class components provide a clear and explicit way to manage component state using the <code>this.state</code> property. This allows developers to have fine-grained control over state management and updates within the component.</p>
<p><strong>Lifecycle Methods:</strong> Class components have access to a range of lifecycle methods such as <code>componentDidMount</code>, <code>componentDidUpdate</code>, and <code>componentWillUnmount</code>. These methods allow developers to hook into different stages of the component's lifecycle, enabling tasks like data fetching, event subscriptions, and cleanup operations.</p>
<p><strong>Instance Methods:</strong> Class components allow you to define custom instance methods directly within the class. These methods encapsulate component logic and can be reused throughout the component. This helps in organizing and structuring the component's codebase.</p>
<p><strong>Legacy Support:</strong> Class components have been a core part of React since its early days and are still widely used in many codebases. They provide backward compatibility and support for legacy projects that may not have been updated to use function components with Hooks.</p>
<p><strong>Robustness:</strong> Class components enforce a more strict structure and separation of concerns, which can lead to more robust and maintainable codebases, especially in larger applications with complex UI logic.</p>
<p><strong>Performance Optimization:</strong> Class components offer optimization opportunities through the use of <code>PureComponent</code> or manual implementation of shouldComponentUpdate (a lifecycle method in React). These optimizations can help prevent unnecessary re-renders and improve performance in certain scenarios.</p>
<h2 id="heading-how-to-handle-complex-state-and-side-effects-before-hooks">How to Handle Complex State and Side Effects (Before Hooks)</h2>
<p>Before the introduction of React Hooks, class components were the primary way of handling complex state and side effects in React applications. Here's how class components facilitated this:</p>
<p><strong>State Management:</strong> Class components provided a built-in mechanism for managing component state using the <code>this.state</code> property. Developers could initialize state in the constructor and update it using the <code>this.setState()</code> method. This allowed for the management of complex state structures and the synchronization of state with the UI.</p>
<p><strong>Lifecycle Methods:</strong> Class components offered a range of lifecycle methods that allowed developers to hook into different stages of a component's lifecycle. These lifecycle methods, such as <code>componentDidMount</code>, <code>componentDidUpdate</code>, and <code>componentWillUnmount</code>, provided opportunities to perform tasks like data fetching, DOM manipulation, or cleanup operations.</p>
<p><strong>Instance Methods:</strong> Class components allowed developers to define custom instance methods directly within the class. These methods encapsulated component logic and allowed for better organization and structure of the component's codebase. Instance methods could handle complex logic, event handling, or interaction with external APIs.</p>
<p><strong>Higher Order Components (HOCs) and Render Props:</strong> Before the widespread adoption of Hooks, developers often used Higher Order Components (HOCs) or Render Props to encapsulate and share complex logic between components. HOCs and Render Props patterns facilitated the reuse of logic across multiple components, making it easier to manage complex state and side effects.</p>
<p>Overall, class components provided a structured and class-based approach to handling complex state and side effects in React applications. While Hooks have since emerged as a more lightweight and function alternative, class components continue to be used in many codebases, especially in legacy projects or situations where specific lifecycle methods or patterns are required.</p>
<h2 id="heading-when-to-use-each-component-type">When to Use Each Component Type</h2>
<p>Let's discuss when to use function components and class components in React, as well as when error boundaries might necessitate the use of class components:</p>
<h3 id="heading-when-to-choose-function-components">When to Choose Function Components</h3>
<p><strong>Simplicity and Readability:</strong> Use function components for simpler UI elements or components that don't require state or lifecycle methods. They have a simpler syntax and are easier to read and understand, making them ideal for presentational components.</p>
<p><strong>Reusability and Composition:</strong> Function components promote reusability and composability by allowing you to create small, composable functions that can be easily reused across your application. They are well-suited for building reusable UI components.</p>
<p><strong>Performance:</strong> Function components with React Hooks offer a more optimized approach to state management and side effects, potentially leading to better performance compared to class components. They avoid the overhead of class instantiation and provide a more lightweight alternative.</p>
<h3 id="heading-when-to-choose-class-components-error-boundaries">When to Choose Class Components (Error Boundaries)</h3>
<p><strong>Lifecycle Methods:</strong> Use class components when you need access to lifecycle methods such as <code>componentDidCatch</code>. Class components provide a way to implement error boundaries, which are components that catch JavaScript errors anywhere in their child component tree and display a fallback UI instead of crashing the whole application.</p>
<p><strong>Handling Complex State and Side Effects (Before Hooks):</strong> In legacy codebases or situations where specific lifecycle methods or optimizations are required, class components might still be the preferred choice. They offer a more structured approach to handling complex state, side effects, and lifecycle behavior.</p>
<p><strong>Backward Compatibility:</strong> Class components are still widely used in many existing React codebases and libraries. If you're working on a project that relies heavily on class components or if you need to integrate with libraries that haven't migrated to function components with Hooks, you may need to use class components for compatibility reasons.</p>
<p>In summary, function components with Hooks are generally preferred for most use cases due to their simplicity, reusability, and performance benefits. However, class components are still relevant, especially when specific lifecycle methods or error boundaries are necessary. It's essential to weigh the pros and cons of each component type and choose the one that best fits your project's requirements and constraints.</p>
<h3 id="heading-react-hooks-bridging-the-gap">React Hooks: Bridging the Gap</h3>
<p>React Hooks are a feature introduced in React 16.8 that allow function components to have stateful logic and access React lifecycle features without needing to write a class component. Hooks are functions that let you use React state and lifecycle features from within function components.</p>
<h3 id="heading-using-hooks-for-state-management-usestate">Using Hooks for State Management (useState)</h3>
<p>The <code>useState</code> Hook is one of the most fundamental React Hooks. It allows function components to manage state without needing to define a class. Here's an example of how to use <code>useState</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

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

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>In this example, <code>useState</code> is used to declare a state variable <code>count</code> and a function <code>setCount</code> to update it. The initial value of <code>count</code> is set to <code>0</code>. Whenever <code>setCount</code> is called with a new value, React will re-render the component with the updated state.</p>
<h3 id="heading-other-useful-hooks-useeffect-usecontext-etc">Other Useful Hooks (useEffect, useContext, etc.)</h3>
<p>React provides several other Hooks for managing side effects, context, and more. Some commonly used ones include:</p>
<p><strong><code>useEffect</code>:</strong> This Hook allows you to perform side effects in function components. It replaces lifecycle methods like <code>componentDidMount</code>, <code>componentDidUpdate</code>, and <code>componentWillUnmount</code>. You can use it to fetch data, subscribe to external events, or perform cleanup.</p>
<p><strong><code>useContext</code>:</strong> This Hook allows you to consume context in function components. It allows you to access values from the nearest <code>Context.Provider</code> in the component tree.</p>
<p><strong><code>useReducer</code>:</strong> This Hook is an alternative to <code>useState</code> for managing more complex state logic. It's based on the reducer pattern and is useful for managing state transitions in a predictable way.</p>
<p><strong><code>useCallback</code> and <code>useMemo</code>:</strong> These Hooks are used for performance optimization. <code>useCallback</code> memoizes functions, preventing unnecessary re-renders, while <code>useMemo</code> memoizes values, preventing expensive calculations on every render.</p>
<p>These are just a few examples of the many Hooks available in React. Each Hook serves a specific purpose and allows function components to have the same capabilities as class components, bridging the gap between the two component types and enabling a more function and composable approach to building React applications.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In summary, React Hooks have made a big impact on how we build components in React. Function components have become really popular because they're simpler and more flexible than class components. </p>
<p>With Hooks, we can easily manage state, handle side effects, and control how components behave. This has made React development more straightforward and efficient.</p>
<p>Looking forward, function components with Hooks are likely to become the standard way of building React applications. They're easier to use and offer better performance, making them a favorite among developers. </p>
<p>While class components still have their place, especially in older projects, the trend is moving towards function components with Hooks. They provide a modern and efficient approach to building user interfaces, making React development more enjoyable for everyone involved.</p>
<p>Connect with me on <a target="_blank" href="https://ng.linkedin.com/in/joan-ayebola">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Marquee Component with React ]]>
                </title>
                <description>
                    <![CDATA[ When you think of marquees, you often envision the vibrant lights and spinning displays at amusement parks, bringing back fond memories of your childhood. Similarly in web applications, marquees inject a lively visual sense by effortlessly grabbing a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-marquee-component-with-react/</link>
                <guid isPermaLink="false">66bb89057a6500a14ba5b767</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Tue, 09 Apr 2024 12:41:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Group-297.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you think of marquees, you often envision the vibrant lights and spinning displays at amusement parks, bringing back fond memories of your childhood.</p>
<p>Similarly in web applications, marquees inject a lively visual sense by effortlessly grabbing attention and infusing your online projects with dynamism.</p>
<p>Join me as we explore how to build an engaging marquee component in React.<br>This step-by-step guide targets everyone regardless of skill level, we aim to make your experience with React both enjoyable and useful.</p>
<h2 id="heading-what-well-cover"><strong>What We'll Cover:</strong></h2>
<ol>
<li><a class="post-section-overview" href="#heading-understanding-marquee-components">Understanding Marquee Components</a></li>
<li><a class="post-section-overview" href="#heading-benefits-of-marquees">Benefits of Marquees</a></li>
<li><a class="post-section-overview" href="#heading-planning-and-designing-the-marquee-component">Planning and Designing the Marquee Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-implement-the-marquee-component">How to Implement the Marquee Component</a></li>
<li><a class="post-section-overview" href="#how-to-enhance-enhance-the-marquee-component">How to Enhance the Marquee Component</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/p/0148db11-7178-4632-b727-2321d7e96b01/best-practices-and-tips-for-marquee-component-development">Best Practices and Tips for Marquee Component Development</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Fundamentals of HTML and CSS</li>
<li>Fundamentals of ES6 JavaScript and React</li>
</ul>
<h2 id="heading-understanding-marquee-components">Understanding Marquee Components</h2>
<p>A marquee represents a continuous section of text or visual content (such as pictures) that scrolls automatically in a horizontal direction.</p>
<p>Although the official <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee">HTML Marquee element</a> is obsolete and its use is heavily discouraged, the concept of scrolling, endless elements to add zest to a webpage is still very much in use, and can be found on numerous modern websites.</p>
<p>This effect is realized through <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations">CSS animations</a>, offering a more efficient, fluid, and lightweight animation outcome.</p>
<p>A visual example of a marquee component from <a target="_blank" href="https://webflow.com/made-in-webflow/website/ujjo-Rebuild">Webflow</a> is shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/00-Example-marquee.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Webflow Example</em></p>
<h2 id="heading-benefits-of-marquees">Benefits of Marquees</h2>
<p>They have a bunch of usefulness such as:</p>
<ul>
<li><strong>Attention-grabbing</strong>: Marquees are excellent for drawing attention to specific content on a webpage. Whether it's a special offer, announcement, or featured content, a moving marquee naturally catches the eye.</li>
<li><strong>Visual Appeal</strong>: Adding a touch of motion to your website enhances its visual appeal. Marquees can bring life to a page, making it more dynamic and engaging for users.</li>
<li><strong>Highlighting Important Information</strong>: When you want to emphasize critical information like breaking news, upcoming events, or urgent messages, a marquee is an effective way to ensure that users don't miss out.</li>
<li><strong>Event Promotion</strong>: They are particularly useful for promoting events or time-sensitive activities. Their scrolling nature allows you to display event details, dates, and highlights space-efficiently.</li>
<li><strong>Ticker-Style Updates</strong>: For displaying real-time updates, such as stock prices, news headlines, or social media feeds, marquees provide a ticker-style format that keeps information continuously flowing for users.</li>
<li><strong>Interactive Banners</strong>: They can serve as interactive banners, allowing users to click on specific items as they scroll by. This can be a creative way to lead users to different sections or pages of your website.</li>
<li><strong>Dynamic Product Showcases</strong>: E-commerce websites can benefit from marquees by showcasing new products or featured items in a visually engaging way, encouraging users to explore the offerings.</li>
<li><strong>Call-to-Action Emphasis</strong>: If you have specific call-to-action messages, using them can give prominence and ensure that they don't go unnoticed.</li>
<li><strong>Breaking Monotony</strong>: In long pages or static content, a well-designed marquee can break the monotony and add an element of surprise, making the user experience more interesting.</li>
<li><strong>Versatility</strong>: They are versatile and can be customized to suit various styles and themes, making them a flexible tool for web designers seeking to create unique and memorable user interfaces.</li>
</ul>
<h2 id="heading-planning-and-designing-the-marquee-component">Planning and Designing the Marquee Component</h2>
<p>Before you start coding, it's important to plan and design your component and consider factors such as:</p>
<ul>
<li><strong>Define Content</strong>: Clearly outline the content you want to display in the component. This could include text, images, or a combination of both.</li>
<li><strong>Scroll Speed</strong>: Determine the desired scrolling speed to be used. Consider the optimal pace for readability and visual appeal.</li>
<li><strong>Visual Design</strong>: Sketch or visualize how you want it to look. Decide on colors, fonts, and any additional styling to align with your overall design scheme.</li>
<li><strong>Behavior at Scroll End</strong>: Consider its behavior when it reaches the end of its scroll position. Decide whether it should loop continuously, bounce back and forth, or have a specific end-state.</li>
<li><strong>User Interaction</strong>: If applicable, plan for any user interaction. This could include pausing on hover or allowing users to click on items within the marquee.</li>
<li><strong>Responsive Design</strong>: Ensure that your component is designed to be responsive, adapting seamlessly to different screen sizes and devices.</li>
<li><strong>Testing Considerations</strong>: Anticipate potential challenges or adjustments needed during the testing phase. Plan for how it will behave on various browsers and devices.</li>
<li><strong>Accessibility</strong>: Keep accessibility in mind, ensuring that users with different disabilities can still access and understand the content within it.</li>
</ul>
<h2 id="heading-how-to-implement-the-marquee-component">How to Implement the Marquee Component</h2>
<p>To implement the component, start by creating a React environment with <a target="_blank" href="https://vitejs.dev/guide/">Vite</a>.</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>After which you navigate to your project directory, install the necessary packages and start up the dev server.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/01-react-server-after-installation-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting up dev server</em></p>
<p>Next, create the elements for the JSX mockup for your component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" main__container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My Marquee<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Default Behaviour<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This includes a header for the component, the behavior of the component and the data in the component to be animated.</p>
<p>It is important to duplicate the data in the component as it would be used to achieve the duplicate effect. However, we’re hiding the second list initially using the <code>aria-hidden='true'</code> property.</p>
<p>To make it more visually appealing, add these styles.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: system-ui, -apple-system, BlinkMacSystemFont, <span class="hljs-string">"Segoe UI"</span>, Roboto,
    Oxygen, Ubuntu, Cantarell, <span class="hljs-string">"Open Sans"</span>, <span class="hljs-string">"Helvetica Neue"</span>, sans-serif;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
}

* { <span class="hljs-attribute">box-sizing</span>: border-box; }

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">600</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.2</span>;
  <span class="hljs-attribute">margin-block</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-tag">h2</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.25rem</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">600</span>;
}

<span class="hljs-selector-tag">section</span> { <span class="hljs-attribute">margin-block</span>: <span class="hljs-number">3rem</span>; }

<span class="hljs-selector-class">.main__container</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">1000px</span>;
  <span class="hljs-attribute">margin-inline</span>: auto;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">124</span>, <span class="hljs-number">145</span>, <span class="hljs-number">175</span>);
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">3rem</span>;
}

<span class="hljs-comment">/* Marquee styles */</span>
<span class="hljs-selector-class">.marquee</span> {
  <span class="hljs-attribute">--gap</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">overflow</span>: hidden;
  <span class="hljs-attribute">user-select</span>: none;
  <span class="hljs-attribute">gap</span>: <span class="hljs-built_in">var</span>(--gap);
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> dashed lightgray;
}

<span class="hljs-selector-class">.marquee__content</span> {
  <span class="hljs-attribute">flex-shrink</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-around;
  <span class="hljs-attribute">gap</span>: <span class="hljs-built_in">var</span>(--gap);
  <span class="hljs-attribute">min-width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.marquee__content</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">object-fit</span>: contain;
}

<span class="hljs-selector-class">.marquee__content</span> &gt; * {
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> auto;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#e8daef</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">2px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span> <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0.25rem</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

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

<span class="hljs-selector-tag">ul</span> { <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">0</span>; }
</code></pre>
<p>At the moment, your component should look like this;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/02-UI-after-applying-styles.png" alt="Image" width="600" height="400" loading="lazy">
<em>UI after applying styles</em></p>
<p>To animate this component, start by defining custom <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes">CSS keyframes</a>.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> scroll {
  <span class="hljs-selector-tag">from</span> { <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">0</span>); }
  <span class="hljs-selector-tag">to</span> { <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(calc(-<span class="hljs-number">100%</span> - var(--gap))); }
}
</code></pre>
<p><strong>Note</strong>: The gap used is the same gap between the marquee items.<br>Then, assign those keyframes to a class.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Enable animation */</span>
<span class="hljs-selector-class">.enable-animation</span> <span class="hljs-selector-class">.marquee__content</span> {
  <span class="hljs-attribute">animation</span>: scroll <span class="hljs-number">10s</span> linear infinite;
}
</code></pre>
<p>Finally, add that class to your section element.</p>
<pre><code class="lang-jsx">&lt;section className=<span class="hljs-string">"enable-animation"</span>&gt;
</code></pre>
<p>And with that, your component should already be animating.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/03-Animated-marquee.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Animated marquee</em></p>
<h2 id="heading-how-to-enhance-the-marquee-component">How to Enhance the Marquee Component</h2>
<p>This component goes beyond the regular infinite animations (as shown above), it often possess some extra functionalities such as:</p>
<ul>
<li><strong>Pause on Hover</strong>: While using a marquee can be beneficial to show a bunch of content more dynamically, the speed of the animation or the position of the information relevant to the user might cause issues, especially for slow readers.</li>
</ul>
<p>To fix this, you can implement a pause functionality to halt it when the user hovers over it. Just add the CSS code below.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Pause on hover */</span>
<span class="hljs-selector-class">.marquee</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-class">.marquee__content</span> {
  <span class="hljs-attribute">animation-play-state</span>: paused;
}
</code></pre>
<p>And with that, it pauses on hover.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/04-Animated-marquee-that-pauses-on-hover.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Animated marquee that pauses on hover</em></p>
<ul>
<li><strong>Reverse on Double Tap:</strong> In the case where a user has passed important information and wants to see it without waiting for the looping animation to bring it back, it’s important to provide a means to achieve that.</li>
</ul>
<p>By double tapping on the component, the animation plays in the opposite direction, showing the information the user just passed. This feature not only promotes accessibility but also gives your web pages a snappy feel, as it provides a quicker way to get information.</p>
<p>To implement this, start by creating a reverse animation state.</p>
<pre><code class="lang-jsx"> <span class="hljs-keyword">const</span> [reverseAnimation, setReverseAnimation] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>The create a function to flip the state of the animation.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> handleDoubleClick = <span class="hljs-function">() =&gt;</span> {
    setReverseAnimation(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> !prev);
  };
</code></pre>
<p>After that, create the CSS class rule to reverse the animation.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">/* Reverse animation */</span>
.marquee--reverse .marquee__content {
  animation-direction: reverse !important;
}
</code></pre>
<p>Then attach the handler function to the component.</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"marquee"</span> onDoubleClick={handleDoubleClick}&gt;
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee__content"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>

      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee__content"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>Finally, conditionally add the reverse class to the component which reverses the animation on double click.</p>
<pre><code class="lang-jsx"> &lt;div className={<span class="hljs-string">`marquee <span class="hljs-subst">${reverseAnimation &amp;&amp; <span class="hljs-string">"marquee--reverse"</span>}</span>`</span>} 
      onDoubleClick={handleDoubleClick}&gt;
</code></pre>
<p>Double-clicking the component now gives;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/05-Animated-marquee-that-revereses-on-double-click.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Animated marquee that reverses on double click</em></p>
<ul>
<li><strong>Pause/Play on Space Bar Click</strong>: Another functionality that can be added to improve UX, especially for keyboard users is to pause or play it on press of the spacebar. This mimics the functionality of how videos work on the web and would help improve accessibility for users.</li>
</ul>
<p>To implement this, start by creating a state to store the current paused state of the animation.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [isAnimationPaused, setIsAnimationPaused] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Then create the CSS rule for the paused state.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">/* Pause animation */</span>
.marquee--paused .marquee__content {
  animation-play-state: paused !important;
}
</code></pre>
<p>After that, create an effect that updates the <code>isAnimationPaused</code> state each time the space bar is pressed.</p>
<pre><code class="lang-jsx"> useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> handleKeyPress = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (event.code === <span class="hljs-string">"Space"</span>) {

        setIsAnimationPaused(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> !prev);
      }
    };
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"keydown"</span>, handleKeyPress);

   <span class="hljs-comment">// Clean-up function when component unmounts</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"keydown"</span>, handleKeyPress);
    };
  }, []);
</code></pre>
<p>This way, the state toggles between true and false based on user presses.<br>Finally, dynamically add the paused class to your component.</p>
<pre><code class="lang-jsx">&lt;div className={<span class="hljs-string">`marquee <span class="hljs-subst">${reverseAnimation &amp;&amp; <span class="hljs-string">"marquee--reverse"</span>}</span> <span class="hljs-subst">${
       isAnimationPaused &amp;&amp; <span class="hljs-string">"marquee--paused"</span>}</span>`</span>} onDoubleClick={handleDoubleClick}&gt;
</code></pre>
<p>And with that, your component pauses and replays each time you press the space bar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/06-Animated-marquee-that-can-be-paused-with-space-bar.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Animated marquee that can be paused with space bar</em></p>
<h2 id="heading-best-practices-and-tips-for-marquee-component-development">Best Practices and Tips for Marquee Component Development</h2>
<p>Some of the best practices to consider when building this component includes:</p>
<ul>
<li><strong>Lazy Loading Images</strong>: In the case where your marquee has a lot of high-quality images which could be large, it is essential to optimize them before building the component.<br><a target="_blank" href="https://daiveedjay.hashnode.dev/implementing-image-lazy-loading-to-improve-website-performance-using-javascript">Lazy loading</a> defers the browser from downloading the images until they are needed (required to be shown in the viewport), cutting down on overall page load time.</li>
</ul>
<p>To achieve this, add <code>loading='lazy'</code> property to your images.</p>
<pre><code class="lang-jsx">&lt;ul className=<span class="hljs-string">"marquee__content"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  &lt;/ul&gt;

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"marquee__content"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{AndroidLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{BehanceLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{GoogleLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{InstagramLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{PaypalLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" marquee__item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SpotifyLogo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
</code></pre>
<ul>
<li><strong>Mindful Animation Speed</strong>: When implementing the animation, it's crucial to strike a careful balance in terms of speed. The animation pace should be visually appealing, capturing the user's attention without sacrificing readability or causing discomfort.<br>This involves thoughtful consideration of how quickly the content scrolls across the screen.<br>By paying attention to animation speed and finding the right balance, you enhance the overall user experience, making it an effective and enjoyable element on your website.</li>
<li><strong>Think of Users with Motion Sensitivity</strong>: Inclusive design means taking into account the needs and preferences of different users, including those with motion sensitivity. Certain users may prefer less movement due to conditions such as vestibular disorders or simply for personal comfort.<br>To support these users, you can use the <code>prefers-reduced-motion</code> media query in your component.</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-comment">/* Pause animation when reduced-motion is set */</span>
@media (prefers-reduced-motion: reduce) {
  .marquee__content {
    animation-play-state: paused !important;
  }
}
</code></pre>
<ul>
<li><strong>Proper Documentation</strong>: Provide clear documentation on how users can use your component effectively so that they won't struggle to use it or don’t miss out on the all the features it has. Consider using labels around the component or a pop-up to convey short instructions on its use.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Your guide to React Marquee Components is complete! From planning to execution, you've dived into creating dynamic scrolling elements for your web projects.</p>
<p>Remember, this component is more than motion—it's an interactive story. Whether sharing crucial info, promoting events, or injecting dynamism, your marquee is a versatile addition to your toolkit.</p>
<p>But this journey is just the beginning. Adjust speeds, consider sensitivities, and adopt best practices to refine your marquee. Let creativity flow, and may your scrolling stories leave a lasting impact.</p>
<p>Prioritize user experience, experiment with enhancements, and let your development shine in the web landscape. Happy scrolling!</p>
<h3 id="heading-contact-information"><strong>Contact Information</strong></h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Reusable React Components ]]>
                </title>
                <description>
                    <![CDATA[ What are reusable React components? You can think of them as building blocks. They are independent pieces of code that can be reused throughout your website to save you time and effort. They can be anything from simple buttons to complex forms. Why U... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-reusable-react-components/</link>
                <guid isPermaLink="false">66bfa1c9a1fd8cc5bc645a0d</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Programming with Shahan ]]>
                </dc:creator>
                <pubDate>Wed, 28 Feb 2024 19:05:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Purple-Blue-Modern-Gradient-New-Blog-Post-Emoji-Twitter-Post--1--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>What are reusable React components? You can think of them as building blocks. They are independent pieces of code that can be reused throughout your website to save you time and effort.</p>
<p>They can be anything from simple buttons to complex forms.</p>
<h2 id="heading-why-use-reusable-components">Why Use Reusable Components?</h2>
<p>As your website grows, you can easily add new features by combining existing components. This makes your code more scalable and adaptable.</p>
<p>You can use your reusable code in future projects without writing it again from scratch.</p>
<h2 id="heading-how-to-make-reusable-react-components">🏭 How to Make Reusable React Components</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Designer--10-_LE_auto_x2_colored.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Illustration credit: <a target="_blank" href="https://www.youtube.com/programmingwithshahan">Shahan</a></em></p>
<p>Here are the two most important things to keep in mind when creating reusable React components:</p>
<h2 id="heading-1-avoid-side-effects">1. 🩼Avoid Side Effects</h2>
<p>Don't put logic that interacts with external data (like making API calls) directly inside a reusable component. Instead, pass this logic as <code>props</code> to the component.</p>
<p>For example, if a button does more than just looking pretty, like fetching data from the internet, it might not be reusable.</p>
<p>This is a reusable button component. But it lacks best practices. I will show you why in the example section.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// This is a reusable button component (bad practice!)</span>
<span class="hljs-keyword">const</span> Button = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span> Click Me <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-2-use-props">2. 🗃️ Use Props</h2>
<p>Props are arguments you pass to a component to customize its behavior and appearance. This allows you to use the same component for different purposes.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// This is a button component that can change its color</span>
<span class="hljs-keyword">const</span> Button = <span class="hljs-function">(<span class="hljs-params">{ color }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> <span class="hljs-attr">color</span> }}&gt;</span> Click Here <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<p>This is still a bad practice because you have a fixed label called "Click Here". If you want to change the text on your button to, let's say: "Sign Up", then you would have to go back to the button component and make that change.</p>
<p>That means every time you want to use a different text, we'd have to go back and edit the code. In other words, it's no longer reusable.</p>
<p><strong>💪 Challenge:</strong> So what's the solution?</p>
<p>You already have the answer. But if you don't, I am going to show you in the example section.</p>
<p><strong>🌴 Hint:</strong> Think about how you might want to use the component in different situations and design it to be flexible and adaptable.</p>
<h2 id="heading-examples-of-reusable-react-components">🍃Examples of Reusable React Components</h2>
<p>Here are some common examples of reusable React components, along with some code examples to get you started:</p>
<h3 id="heading-buttons">Buttons</h3>
<p>Basic buttons with different styles and functionalities.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Button component</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> Button = <span class="hljs-function">(<span class="hljs-params">{ color, label, onClick }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">padding-2</span> <span class="hljs-attr">shadow-none</span> <span class="hljs-attr">hover:shadow</span> <span class="hljs-attr">background-light-</span>${<span class="hljs-attr">color</span>} <span class="hljs-attr">hover:background-dark-</span>${<span class="hljs-attr">color</span>}`}
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>
    &gt;</span>
      {label}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Button;

<span class="hljs-comment">// Using the Button component</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"blue"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Click Here"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> console.log("Button clicked!")} /&gt;</span>
</code></pre>
<p>As you can see, I did not write "Click Here" in the <code>button</code> component. I want to make my button reusable, and thus it doesn't know anything about custom styles or texts.</p>
<p>So, I passed them as props (i.e., color, label, and onClick) to change them in the future without touching the original button components. Hope that makes it clear.</p>
<p><strong>🪜Solution:</strong> You need to pass each functionality as <code>props</code> in the reusable component.</p>
<h3 id="heading-navbars">Navbars</h3>
<p>Navigation bars that provide consistent navigation across your website.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Navbar component</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> Navbar = <span class="hljs-function">(<span class="hljs-params">{ isLoggedIn }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navbar"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navbar-container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navbar-logo"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"navbar-links"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          {isLoggedIn ? (
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/profile"</span>&gt;</span>Profile<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          ) : (
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/login"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          )}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Navbar;

<span class="hljs-comment">// Using the Navbar component</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> <span class="hljs-attr">isLoggedIn</span>=<span class="hljs-string">{true}</span> /&gt;</span></span>
</code></pre>
<p>As you can see, I passed  <code>&lt;Navbar isLoggedIn={true} /&gt;</code></p>
<p>This line utilizes the <code>Navbar</code> component and passes the <code>isLoggedIn</code> prop with a value of <code>true</code>, indicating the user is logged in. This will display the "Profile" link and hide the "Login" link. </p>
<p>Similar to the button component, the <code>Navbar</code> component is reusable and accepts props to customize its behavior. Perfect!</p>
<h3 id="heading-why-api-calls-in-a-button-component-is-a-bad-practice">Why API Calls in a Button Component is a Bad Practice</h3>
<p>Now, you understand everything about reusable components in React.</p>
<p>Let's dig deeper by solving a complex problem.</p>
<p>Consider the scenario where you have a button that does an API call. The code for the button component can be the following:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>; 
<span class="hljs-keyword">import</span> doAPICall <span class="hljs-keyword">from</span> <span class="hljs-string">"../api"</span>

<span class="hljs-keyword">const</span> SaveButton  = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
        doAPICall();
      }}
    &gt;
      Save
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SaveButton
</code></pre>
<p>It is quite clear that you can’t reuse the above button in multiple places as this button component contains a side-effect (<code>doAPICall()</code>) inside it.</p>
<p>You can make this component reusable. First, you'll have to extract out the side-effect and pass that as a prop to the button component like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span>  {
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doAPICall</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Does an API call to save the current state of the app.</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SaveButton</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{doAPICall}/</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>The button component should look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> SaveButton  = <span class="hljs-function">(<span class="hljs-params">{
  onClick
}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>
    &gt;</span>
      Save
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<p>As you can see, the above button can now be reused anywhere you want to save data with the click of a button. The button can now be used like this in multiple places:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span>  {
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveUser</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Does an API call to save the user.</span>
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveProject</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Does an API call to save the project.</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SaveButton</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{saveUser}/</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SaveButton</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{saveProject}/</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>You can also make the button component more reusable by using a prop to control the label:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span>  {
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveUser</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Does an API call to save the user.</span>
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveProject</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Does an API call to save the project.</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SaveButton</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{saveUser}</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Save user"</span>  /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SaveButton</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{saveProject}</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Save project"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>The button component should look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> SaveButton  = <span class="hljs-function">(<span class="hljs-params">{
  onClick,
  label
}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>
    &gt;</span>
      {label}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-conclusion">👏Conclusion</h2>
<p>Congratulations! You've successfully learned how to build reusable React components. </p>
<p>Remember, reusable components are the building blocks of robust React development. By practicing reusable components, you can build cleaner, more efficient, and more maintainable React applications. </p>
<p>The more you practice, the better you'll become at identifying opportunities to use them in your projects!</p>
<p><strong>Read More:</strong> <a target="_blank" href="https://dev.to/codewithshahan/the-future-of-frontend-development-1amd">The Future of Frontend Development</a></p>
<p>Thank you for taking the time to read this article. Until next time.. Keep learning and you can follow me on <strong><a target="_blank" href="https://twitter.com/shahancd">𝕏</a></strong>  for latest updates on programming and productivity. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Render an Array of Components in React ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, I will show you how using indices to render an array of components in React can be problematic. I'll also teach you how to mitigate array rendering issues with unique ids. As always, we'll work on a real world example and solve prob... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-render-array-of-components-in-react/</link>
                <guid isPermaLink="false">66bc4d10cd8a65d579e3a960</guid>
                
                    <category>
                        <![CDATA[ arrays ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matéu.sh ]]>
                </dc:creator>
                <pubDate>Tue, 27 Feb 2024 19:18:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Array-components.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, I will show you how using indices to render an array of components in React can be problematic. I'll also teach you how to mitigate array rendering issues with unique ids.</p>
<p>As always, we'll work on a real world example and solve problem I stumbled across while building my 2048 Game in React. All the code snippets are inspired by this project. If you want to review the code before reading this article, you can <a target="_blank" href="https://mateuszsokola.github.io/2048-in-react/">find it on GitHub</a>.</p>
<h2 id="heading-the-2048-game">The 2048 Game</h2>
<p>Let me explain the rules of the 2048 game first. The player must combine tiles that have the same numbers until they reach the number 2048. The tiles can contain only numbers that represent a power of two starting from 2 – this means 2, 4, 8, 16, 32, and so on – until they reach the number 2048. The board has dimensions of 4 x 4 tiles, so that it can fit up to 16 tiles.</p>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/demo-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>2048 Game Preview</em></p>
<p>In this article, I will only teach you how to render arrays in React and show you some best practices when comes to rendering lists in React components. </p>
<p>Unfortunately, we cannot create the entire game because it would make this article confusing. But if you want to do it from scratch, you should consider enrolling to my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">course on Udemy</a> where I will walk you through creating the 2048 Game with animations in React 18.</p>
<h2 id="heading-prerequisites"><strong>P</strong>rerequisites<em>**</em></h2>
<p>Before we start, make sure you know some basics of React. Nothing sophisticated – just be sure you've worked with React before, otherwise you might feel a bit lost.</p>
<p>If you don't yet know React, freeCodeCamp has a <a target="_blank" href="https://www.freecodecamp.org/news/learn-react-course/">5-hour React course for beginners</a> so feel free to watch it before reading this article. You can also enroll in my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course</a>.</p>
<p>Now let's get started.</p>
<h2 id="heading-how-to-render-array-elements"><strong>How to Render Array Elements</strong></h2>
<p>As I mentioned at the beginning, the game board has dimensions of 4 x 4 tiles. That means the best data structure to store tiles on the board will be a multidimensional array, like the one you see below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> board = [
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
]
</code></pre>
<p>Unfortunately, this data structure will be expensive, since it requires nested loops iterating across each other. That's why I decided to flatten this array into a one-dimensional one:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
</code></pre>
<p>As you can see, there are a lot of empty elements in this array, and it gives room for further improvements. We can reduce the amount of operations by replacing tile values with objects containing tile information. </p>
<p>For example, you can introduce a new type to store the meta data of every tile like this:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> TileModel = {
  position: [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>];
  value: <span class="hljs-built_in">number</span>;
};
</code></pre>
<p>As you can see, this data type makes tiles smart. Every tile will know its position and value. I decided to store the position as an array of two elements. These elements will represent <code>x</code> and <code>y</code> coordinates. Rather than pixels, I will use array indices on the board array I mentioned in the first step.</p>
<p>Now let's improve the <code>tilesOnBoard</code> array and make it store only existing tiles without empty values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [
    { <span class="hljs-attr">position</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
    { <span class="hljs-attr">position</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
]
</code></pre>
<p>Thanks to this simplification, I can render tiles by using the simple <code>map</code> functor that will iterate through all array elements and create Tile components out of them.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> renderTiles = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> tilesOnBoard.map(<span class="hljs-function">(<span class="hljs-params">tile: TileModel, index: number</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tile</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> {<span class="hljs-attr">...tile</span>} /&gt;</span></span>
  ));
};
</code></pre>
<p>Let's focus on the second argument of the <code>map</code> functor for a moment. As you can see, it uses the item index of the <code>tilesOnBoard</code> array. I am using it as a <code>key</code> property to initialize React components – in this case <code>Tile</code> components.</p>
<p>If you've never used <code>key</code> props, React needs keys to identify which elements have changed, are added, or are removed. Keys should be assigned to every item inside the array of components. </p>
<p>That's why I assigned array indices to all tiles. Unfortunately, array indices aren't the best unique identifiers, as you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/array-indexes.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Strange behavior when array indices are used as key props</em></p>
<p>It might be hard to spot what's happening here, so let me briefly explain. Basically, React is reusing existing HTML elements to render new tiles. This isn't an intended behavior – instead, I should have removed merged tiles and created a new tile after every move. </p>
<p>But why is this happening? After the tiles are getting merged, a new tile is created, and that means the array still has two elements with the same array indices. </p>
<p>React uses a mechanism called the Virtual DOM to detect changes and modify elements on the DOM tree. Unfortunately, this mechanism is optimized for speed so that it doesn't analyze the entire component but only the <code>key</code> prop. This means React cannot differentiate the new tile creation from a style change on an existing div element. That's why we are experiencing this issue.  </p>
<p>To confirm that my reasoning is right, let's take a brief look at the <em>Element</em> tab in Chrome DevTools:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/reusing-html-elements.gif" alt="Image" width="600" height="400" loading="lazy">
<em>DOM Element reusability due to array indices used as key props</em></p>
<p>As you can see, two existing div elements only changed their style attributes but nothing was added or removed. This isn't an intended behavior, but it tells us that array indices are poor unique identifiers for React components.</p>
<p>If you aren't familiar with Chrome Developer Tools, you should read my article on implementing <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-mobile-swiping-component-in-react/">mobile touch events in React 18</a> where I do a deep dive on how to use it. </p>
<h2 id="heading-unique-identifiers-as-key-props"><strong>Unique Identifiers As Key Props</strong></h2>
<p>To fixing array rendering problems in React, we'll need to use some unique identifiers such as incremental ids, uuids, or others. To focus on the essentials, I decided to use a library called <code>uid</code>, which you can install by running the following in your terminal: </p>
<pre><code class="lang-bash">npm install --save uid
</code></pre>
<p>Now I need to modify tiles to support those identifiers. First, I added a new property <code>id</code> in the tile meta data type:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> TileModel = {
  id: <span class="hljs-built_in">string</span>;
  position: [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>];
  value: <span class="hljs-built_in">number</span>;
};
</code></pre>
<p>And I assigned an id to every element in the  <code>tilesOnBoard</code> array (here's where the <code>uid</code> library comes into play):</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tilesOnBoard = [
    { <span class="hljs-attr">id</span>: uid(), <span class="hljs-attr">position</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
    { <span class="hljs-attr">id</span>: uid(), <span class="hljs-attr">position</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>], <span class="hljs-attr">value</span>: <span class="hljs-number">2</span> },
]
</code></pre>
<p>The last thing I did was to change the <code>renderTiles</code> helper:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> renderTiles = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> tilesOnBoard.map(<span class="hljs-function">(<span class="hljs-params">tile: TileModel</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tile</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{tile.id}</span> {<span class="hljs-attr">...tile</span>} /&gt;</span></span>
  ));
};
</code></pre>
<p>As you can see, I removed an index argument from the <code>map</code> functor, and replaced the <code>key</code> prop with an unique id which I added to the tile meta data.</p>
<p>Now the 2048 game works like a charm:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/array-tile-ids.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, you learned that indices aren't the best option to render arrays of components in React and that they might lead to strange behaviors. If there is only one thing you should remember from this article it's that you should always use unique identifies as the <code>key</code> prop of React components.</p>
<p>Wanna learn more tricks like this one? You should join to my <a target="_blank" href="https://www.udemy.com/course/2048-in-react-and-nextjs/?referralCode=AC3FD6336BAB9C402106">React 18 course on Udemy</a>. I will teach you how to <strong>create 2048 game in React</strong> from scratch and show you solutions to the most common mistakes React developers make.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a High-Performance Tab Component in React ]]>
                </title>
                <description>
                    <![CDATA[ Tabs are more than mere UI elements – they're the backbone of user navigation and content organization in many applications. In React, crafting a tabbed component that's both efficient and responsive is not just an improvement, it's a necessity. This... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-high-performance-tab-component/</link>
                <guid isPermaLink="false">66bb88faadd24ba4273250e0</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Thu, 18 Jan 2024 16:01:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/tabbed-cover-image-new.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Tabs are more than mere UI elements – they're the backbone of user navigation and content organization in many applications. In React, crafting a tabbed component that's both efficient and responsive is not just an improvement, it's a necessity.</p>
<p>This article takes a deep dive into constructing a React tab component that excels in performance and user experience. We'll cover how to create, optimize, and animate tabs effectively.</p>
<p>You'll also learn how to leverage the Profiler in Dev Tools to pinpoint and reduce unnecessary re-renders, and how to apply Framer Motion to elevate your tabs beyond the functional to make them delightful.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ul>
<li>Fundamentals of HTML and CSS</li>
<li>Fundamentals of ES6 JavaScript</li>
<li>Fundamentals of React and Framer Motion.</li>
</ul>
<h2 id="heading-what-well-cover"><strong>What We'll Cover:</strong></h2>
<ol>
<li><a class="post-section-overview" href="#heading-how-to-set-up-an-environment">How to set up an environment</a></li>
<li><a class="post-section-overview" href="#heading-the-heart-of-the-tab-component">The Heart of the Tab component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-tab-component">How to build the Tab component</a><br>– <a class="post-section-overview" href="#heading-how-to-build-the-ui">How to build the UI</a><br>– <a class="post-section-overview" href="#heading-how-to-implement-the-tab-functionality">How to implement the Tab functionality</a><br>– <a class="post-section-overview" href="#heading-how-to-optimize-the-tab-component">How to optimize the Tab component</a><br>– <a class="post-section-overview" href="#heading-how-to-animate-the-component">How to animate the component</a></li>
<li><a class="post-section-overview" href="#heading-other-methods-you-can-use-to-fine-tune-for-high-performance">Other methods you can use to fine-tune for high performance</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-how-to-set-up-an-environment">How to Set Up an Environment</h2>
<p>To build a high-performance React tab component, the first thing to do is set up a clean development environment. </p>
<p>Before you dive into creating React components, make sure to install <a target="_blank" href="https://nodejs.org/en/download">Node.js</a> on your computer. This sets the stage for an efficient development process.</p>
<h2 id="heading-how-to-create-a-react-project">How to Create a React Project</h2>
<p>After installing Node.js, use Vite (a modern build tool for React projects) to create a new React project. In your local terminal, run the command:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>Select React as your framework and your preferred variant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/0-React-app-set-up.png" alt="Image" width="600" height="400" loading="lazy">
<em>React app setup</em></p>
<p>Then to install the necessary packages, run <code>npm install</code> and open it in your IDE.</p>
<p>At the moment, your app should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/1-React-app-setup.png" alt="Image" width="600" height="400" loading="lazy">
<em>React app setup complete</em></p>
<p>Finally, start up the dev server by running <code>npm run dev</code> and go to the given port.</p>
<h2 id="heading-the-heart-of-the-tab-component">The Heart of the Tab Component</h2>
<p>Imagine the tab component like a smart switchboard, smoothly guiding you through different content sections—similar to flipping TV channels or tuning in to radio stations. </p>
<p>Two main parts make this happen:</p>
<ul>
<li><strong>Tab Buttons</strong>: These act like selector switches, holding individual tabs ready for your clicks. Clicking on these tabs is like choosing different views or content channels.</li>
<li><strong>Tab Panels</strong>: Think of these as the content broadcasts linked to each tab. Only the content connected to the active tab is in the spotlight, just like tuning into a specific channel for clear viewing.</li>
</ul>
<h2 id="heading-how-to-build-the-tab-component">How to Build the Tab Component</h2>
<p>This section includes 4 parts:</p>
<ol>
<li>Building the UI</li>
<li>Implementing the tab functionality</li>
<li>Optimizing the tab component</li>
<li>How to Animate the Component</li>
</ol>
<h3 id="heading-how-to-build-the-ui">How to Build the UI</h3>
<p>This section includes all of the mockups and styling needed to render your component on the page. Here’s a step-by-step walkthrough of the process:</p>
<p>First, create an array containing all the data used by your app in your App component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> petData = [
    {
      <span class="hljs-attr">animal</span>: <span class="hljs-string">"Cheetah"</span>,
      <span class="hljs-attr">fact</span>: <span class="hljs-string">"Cheetahs are the fastest land animals, capable of reaching speeds up to 75 mph."</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/6.svg"</span>,
    },
    {
      <span class="hljs-attr">animal</span>: <span class="hljs-string">"Koala"</span>,
      <span class="hljs-attr">fact</span>: <span class="hljs-string">"Koalas sleep around 20 hours a day and are known for their eucalyptus diet."</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/3.svg"</span>,
    },
    {
      <span class="hljs-attr">animal</span>: <span class="hljs-string">"Elephant"</span>,
      <span class="hljs-attr">fact</span>: <span class="hljs-string">"Elephants have the largest brains among land animals and demonstrate remarkable intelligence."</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/1.svg"</span>,
    },
    {
      <span class="hljs-attr">animal</span>: <span class="hljs-string">"Zebra"</span>,
      <span class="hljs-attr">fact</span>: <span class="hljs-string">"Zebras have distinctive black and white stripes that act as a natural defense against predators."</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/7.svg"</span>,
    },
    {
      <span class="hljs-attr">animal</span>: <span class="hljs-string">"Horse"</span>,
      <span class="hljs-attr">fact</span>: <span class="hljs-string">"Horses have excellent memory and are capable of recognizing human emotions."</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/5.svg"</span>,
    },
  ];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main__container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Choose your pet<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Then create two components <code>TabButtons</code> and <code>TabContent</code> which will control the Tab and display the Tab’s content, respectively. Then import them into the App component.</p>
<p>Next, pass the data array from your app component into both components using props.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Rest of app component</span>
<span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main__container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Choose your pet<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TabButtons</span>

        <span class="hljs-attr">petData</span>=<span class="hljs-string">{petData}</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TabContent</span> <span class="hljs-attr">petData</span>=<span class="hljs-string">{petData}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
</code></pre>
<p>Then loop over the data in both components to create the buttons that'll be used to control the component and the data shown with respect to each tab.</p>
<p>For the <code>TabButtons</code> component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TabButtons</span>(<span class="hljs-params">{ petData }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
      {petData.map((item, index) =&gt; (
               <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">tab__button</span>`}
          <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
                 &gt;</span>
          {item.animal}
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>The <code>TabContent</code> component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TabContent</span>(<span class="hljs-params">{ petData}</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
        {petData.map((pet) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{pet}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{pet.image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{pet.fact}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>For styling, use this CSS which contains all the styles needed for the entire app in your <code>App.css</code> file:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&amp;display=swap"</span>);

* {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">62.5%</span>;
}

<span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--text-color</span>: <span class="hljs-number">#9eb25d</span>;
  <span class="hljs-attribute">--bg-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">238</span>, <span class="hljs-number">252</span>, <span class="hljs-number">206</span>, <span class="hljs-number">0.4</span>);
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Space Grotesk"</span>, sans-serif;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100</span>dvh;
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
}

<span class="hljs-selector-class">.main__container</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">4rem</span>;

  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">4rem</span>;

  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Space Grotesk"</span>, sans-serif;
  <span class="hljs-attribute">width</span>: max-content;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">8rem</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--text-color);
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--bg-color);
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">3px</span> <span class="hljs-number">3px</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
}

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">4rem</span>;
}
<span class="hljs-selector-class">.tab__header</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">list-style</span>: none;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.tab__header</span> <span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-built_in">var</span>(--text-color);
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">border-top-right-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">border-top-left-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.tab__container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">4rem</span>;
  <span class="hljs-attribute">box-shadow</span>: inset -<span class="hljs-number">3px</span> -<span class="hljs-number">3px</span> <span class="hljs-number">3px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>),
    inset <span class="hljs-number">3px</span> <span class="hljs-number">3px</span> <span class="hljs-number">3px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.tab__content</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">25rem</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-built_in">var</span>(--text-color);
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-between;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">4rem</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.tab__content</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">31rem</span>;
  <span class="hljs-attribute">max-height</span>: <span class="hljs-number">20rem</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.tab__content</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.active</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--text-color);

  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">600</span>;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">1000px</span>) {
  <span class="hljs-selector-class">.main__container</span> {
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">95%</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">5rem</span> auto;
  }

  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;
  }

  <span class="hljs-selector-class">.tab__header</span> {
    <span class="hljs-attribute">flex-wrap</span>: wrap;
  }

  <span class="hljs-selector-class">.tab__content</span> {
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">min-height</span>: <span class="hljs-number">35rem</span>;
  }
  <span class="hljs-selector-class">.tab__header</span> <span class="hljs-selector-tag">li</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.6rem</span>;
  }

  <span class="hljs-selector-class">.tab__container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  }

  <span class="hljs-selector-class">.tab__content</span> <span class="hljs-selector-tag">img</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">150px</span>;
  }

  <span class="hljs-selector-class">.tab__content</span> <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.6rem</span>;
  }
}
</code></pre>
<p>Or you can alternatively go here for the stylings: <a target="_blank" href="https://github.com/Daiveedjay/React-Tab/blob/main/src/App.css">CSS File</a></p>
<p>At the moment, your page should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/2-Initial-page-after-looping-over-data-array.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initial page after looping over data array</em></p>
<h3 id="heading-how-to-implement-the-tab-functionality">How to Implement the Tab Functionality</h3>
<p>To create a tab component that functions smoothly, you need to manage which tab is currently active. Think of it as showing only one content section at a time. </p>
<p>To achieve this, start by establishing a 'state' in the App component. This state will keep track of the currently active tab.</p>
<pre><code class="lang-js">  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
</code></pre>
<p>The active state is initialized with the index of the tab you want to start with.</p>
<p>Then it's used to show only the the data associated with that index.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TabContent</span>(<span class="hljs-params">{ petData, activeTab }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
        {/ Using the active index to select a particular data /}
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> {petData[activeTab].fact}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Which shows just the first item from the data array:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/3-Showing-one-data-from-the-array.png" alt="Image" width="600" height="400" loading="lazy">
<em>Showing one data item from the array</em></p>
<p>You can achieve the tab switching functionality by updating the state of the active tab using its setter function. </p>
<p>Start by passing the setter function and the active tab state into the tab buttons via props.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> petData = [ <span class="hljs-comment">//...data ];</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main__container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Choose your pet<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TabButtons</span>
        <span class="hljs-attr">activeTab</span>=<span class="hljs-string">{activeTab}</span>
        <span class="hljs-attr">setActiveTab</span>=<span class="hljs-string">{setActiveTab}</span>
        <span class="hljs-attr">petData</span>=<span class="hljs-string">{petData}</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TabContent</span> <span class="hljs-attr">activeTab</span>=<span class="hljs-string">{activeTab}</span> <span class="hljs-attr">petData</span>=<span class="hljs-string">{petData}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Then use the setter function to set the value of the active state into the corresponding data via the index.</p>
<pre><code class="lang-js">
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TabButtons</span>(<span class="hljs-params">{ petData, activeTab, setActiveTab }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
      {petData.map((item, index) =&gt; (
               <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">tab__button</span>`}
          <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
          {item.animal}
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>With that, your tab component works and can display dynamic data based on the button you click on. Congrats!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/2-Testing-out-the-tab-functionality.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Testing out the tab functionality</em></p>
<p>To improve the UX, add an active class to the currently clicked tab using its index. This applies the active class to the tab whose index value is the same as the value stored in the active state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TabButtons</span>(<span class="hljs-params">{ petData, activeTab, setActiveTab }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
      {petData.map((item, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
          // <span class="hljs-attr">Adding</span> <span class="hljs-attr">an</span> <span class="hljs-attr">active</span> <span class="hljs-attr">class</span> <span class="hljs-attr">where</span> <span class="hljs-attr">the</span> <span class="hljs-attr">current</span> <span class="hljs-attr">index</span> <span class="hljs-attr">matches</span> <span class="hljs-attr">the</span> <span class="hljs-attr">currently</span> <span class="hljs-attr">active</span> <span class="hljs-attr">tab</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
          <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
          {item.animal}
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Which yields the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/1-tab-functionality-after-adding-active-class-to-tab.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tab functionality after adding active class to tab</em></p>
<h3 id="heading-how-to-optimize-the-tab-component">How to Optimize the Tab Component</h3>
<p>While your tab component seems ready to go, there are still modifications you can make to better enhance it in terms of performance. For this, you can use <a target="_blank" href="https://react.dev/learn/react-developer-tools">React Dev Tools</a>. </p>
<p>This is a browser extension which provides a ton of useful tools React developers can use to inspect and debug their applications. Head over to your browser web store and download the extension.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/3-Downloading-the-React-dev-tools.png" alt="Image" width="600" height="400" loading="lazy">
<em>Downloading React dev tools</em></p>
<p>After you install it, inspecting any React website from your browser dev tools shows two new tabs called <code>⚛️Components</code> and <code>⚛️Profiler</code>.</p>
<p>In this application, we’ll be using the Profiler, which is used to measure how many times the React application is rendered, how many components are rendered, and how much time the components take to be rendered.</p>
<p>For your application, inspect your React app and open up the profiler from the top right of your screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/IMG-20240116-WA0000.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding the profiler in dev tools</em></p>
<p>In your profiler, click on the blue record button and start a recording of your React app to track changes and renders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/3-using-the-profiler-to-test-changes.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Using the profiler to test changes</em></p>
<p>The result from my end is a total of 0.6ms for the total render time with all 3 components re-rendering (<code>App</code> = 0.2ms, <code>TabButtons</code> = 0.3ms and <code>TabContent</code> = 0.1ms).</p>
<p>The entire render time is quite acceptable, but there is room for improvement.</p>
<p>With the profiler indicating that the app component triggered the re-render, let’s optimize our application to reduce excessive re-renders with the following steps.</p>
<p>Start by creating a <code>Tab</code> component and lifting the data array and the state into that <code>Tab</code> component. You do this because this is the component that consumes the data and state and not the App component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> petData = [
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Cheetah"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Cheetahs are the fastest land animals, capable of reaching speeds up to 75 mph."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/6.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Koala"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Koalas sleep around 20 hours a day and are known for their eucalyptus diet."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/3.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Elephant"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Elephants have the largest brains among land animals and demonstrate remarkable intelligence."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/1.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Zebra"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Zebras have distinctive black and white stripes that act as a natural defense against predators."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/7.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Horse"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Horses have excellent memory and are capable of recognizing human emotions."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/5.svg"</span>,
  },
];

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span></span>;
}
</code></pre>
<p>Then locally create the JSX for this project. This removes the need for creating excessive components just for JSX.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
        {petData.map((item, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
            <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
            {item.animal}
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> {petData[activeTab].fact}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>And now re-running the profiler with your new app structure yields the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/4-profiler-after-optimizing-app.png" alt="Image" width="600" height="400" loading="lazy">
<em>Profiler after optimizing app</em></p>
<p>As you can see, the new rendering time is 0.3ms, improving the speed by 50%, with the app component not re-rendering and the extra JSX elements removed.</p>
<p>It's important to note that this example is relative to the size of the tab component. In larger ones, it’s fairly common to see the tab component broken down into smaller components but in the same file.</p>
<h3 id="heading-how-to-animate-the-component">How to Animate the Component</h3>
<p>For animation, we’ll be using Framer Motion, an open-source animation library designed for React. It delivers a straightforward and expressive API for generating intricate animations. </p>
<p>For a more in-depth explanation of how the library works, check out this guide on <a target="_blank" href="https://www.freecodecamp.org/news/improve-user-experience-in-react-by-animating-routes-using-framer-motion/">using framer motion to animate routes in React</a>.</p>
<p>To use the library, start by installing it in your project using the prompt:</p>
<pre><code class="lang-bash">npm i framer-motion
</code></pre>
<p>Then import the required properties from the library.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { AnimatePresence, motion } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;
</code></pre>
<p>Next, make all the elements you want to animate motion elements.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
            {petData.map((item, index) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
                <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
                {item.animal}
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.img</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span>
              <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.p</span>&gt;</span>
              {petData[activeTab].fact}
            <span class="hljs-tag">&lt;/<span class="hljs-name">motion.p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span>

    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>Then create animation objects for the elements you want to animate. For your tab, this create a scale in animation for the image and a fade and slide animation for the text.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> contentVariants = {
  <span class="hljs-attr">initial</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"100%"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">animate</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"0"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span> },
  <span class="hljs-attr">exit</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"100%"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
};

<span class="hljs-keyword">const</span> imgVariants = {
  <span class="hljs-attr">initial</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">0.1</span> },
  <span class="hljs-attr">animate</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">1</span> },
  <span class="hljs-attr">exit</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">0.1</span> },
};
</code></pre>
<p>After that, pass them into the JSX, specifying their initial, animated, and exit states. </p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{activeTab}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
            {petData.map((item, index) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
                <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
                {item.animal}
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.img</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span>
              <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{imgVariants}</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.p</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{contentVariants}</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}&gt;</span>
              {petData[activeTab].fact}
            <span class="hljs-tag">&lt;/<span class="hljs-name">motion.p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span>

    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>Finally, wrap your component with the <code>AnimatePresence</code> component to detect when you switch between tabs to fire exit animations:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AnimatePresence</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"wait"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{activeTab}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
            {petData.map((item, index) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
                <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
                {item.animal}
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.img</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span>
              <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{imgVariants}</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.p</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{contentVariants}</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}&gt;</span>
              {petData[activeTab].fact}
            <span class="hljs-tag">&lt;/<span class="hljs-name">motion.p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">AnimatePresence</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p><strong>Note</strong>: Framer motion uses the key prop to detect changes between elements. The mode prop set to wait in <code>AnimatePresense</code> helps framer motion fire exit animations before entry animations.</p>
<p>And with that, your Tab component is fully functional and animated. Bravo! 🎈</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/tab-component-fully-functional-and-animated-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>tabbed component fully functional and animated</em></p>
<p>For reference, here’s the full code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { AnimatePresence, motion } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;

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

<span class="hljs-keyword">const</span> petData = [
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Cheetah"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Cheetahs are the fastest land animals, capable of reaching speeds up to 75 mph."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/6.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Koala"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Koalas sleep around 20 hours a day and are known for their eucalyptus diet."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/3.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Elephant"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Elephants have the largest brains among land animals and demonstrate remarkable intelligence."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/1.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Zebra"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Zebras have distinctive black and white stripes that act as a natural defense against predators."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/7.svg"</span>,
  },
  {
    <span class="hljs-attr">animal</span>: <span class="hljs-string">"Horse"</span>,
    <span class="hljs-attr">fact</span>: <span class="hljs-string">"Horses have excellent memory and are capable of recognizing human emotions."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"../src/assets/5.svg"</span>,
  },
];

<span class="hljs-keyword">const</span> contentVariants = {
  <span class="hljs-attr">initial</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"100%"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
  <span class="hljs-attr">animate</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"0"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span> },
  <span class="hljs-attr">exit</span>: { <span class="hljs-attr">y</span>: <span class="hljs-string">"100%"</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
};

<span class="hljs-keyword">const</span> imgVariants = {
  <span class="hljs-attr">initial</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">0.1</span> },
  <span class="hljs-attr">animate</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">1</span> },
  <span class="hljs-attr">exit</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">0.1</span> },
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Tab</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeTab, setActiveTab] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AnimatePresence</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"wait"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__container"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{activeTab}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__header"</span>&gt;</span>
            {petData.map((item, index) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span> === <span class="hljs-string">activeTab</span> &amp;&amp; "<span class="hljs-attr">active</span>"} <span class="hljs-attr">tab__button</span>`}
                <span class="hljs-attr">key</span>=<span class="hljs-string">{item.animal}</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveTab(index)}&gt;
                {item.animal}
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tab__content"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.img</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">{petData[activeTab].image}</span>
              <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{imgVariants}</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">motion.p</span>
              <span class="hljs-attr">variants</span>=<span class="hljs-string">{contentVariants}</span>
              <span class="hljs-attr">initial</span>=<span class="hljs-string">"initial"</span>
              <span class="hljs-attr">animate</span>=<span class="hljs-string">"animate"</span>
              <span class="hljs-attr">exit</span>=<span class="hljs-string">"exit"</span>
              <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.5</span> }}&gt;</span>
              {petData[activeTab].fact}
            <span class="hljs-tag">&lt;/<span class="hljs-name">motion.p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">AnimatePresence</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-other-methods-you-can-use-to-fine-tune-for-high-performance">Other Methods You Can Use to Fine-Tune for High Performance</h2>
<p>While your React tab component is functional and animated, there are opportunities for further optimization to ensure high performance, especially in scenarios involving larger datasets or asynchronous data fetching. Let's explore some strategies to fine-tune your tab component.</p>
<h3 id="heading-data-considerations">Data Considerations</h3>
<ul>
<li>Size of the Tab Component: Check the size of your tab component, especially if dealing with a large amount of data. Consider lazy-loading or pagination to improve initial rendering times.</li>
<li>Asynchronous Data Loading: If your data is asynchronous, implement loading states to enhance user experience. Optimize the rendering logic to handle data loading efficiently.</li>
</ul>
<h3 id="heading-react-profiler">React Profiler</h3>
<ul>
<li>Identifying and Reducing Unnecessary Re-renders: Outside leveraging React DevTools Profiler to analyze component rendering behaviour, use React hooks like React.memo and React.callback to optimize and cache your data.</li>
</ul>
<h3 id="heading-component-structure">Component Structure</h3>
<ul>
<li>Granular Component Structure: For larger tab components, consider breaking down the structure into smaller, granular components. This allows for better maintainability and can improve rendering performance.</li>
</ul>
<h3 id="heading-code-splitting">Code Splitting</h3>
<ul>
<li>Dynamic Imports for Code Splitting: Implement dynamic imports for code splitting, especially if your React application becomes more complex. This ensures that only the necessary code loads when a specific tab is selected.</li>
</ul>
<h3 id="heading-responsive-design">Responsive Design</h3>
<ul>
<li>Optimizing for Different Viewports: Ensure your tab component is responsive to different screen sizes. Consider media queries and adaptive design to provide an optimal experience across various devices.</li>
</ul>
<h3 id="heading-browser-caching">Browser Caching</h3>
<ul>
<li>Optimizing Assets with Browser Caching: Leverage browser caching for static assets, such as images, to reduce load times. Consider optimizing and compressing images to cut their impact on performance.</li>
</ul>
<h3 id="heading-testing-and-profiling">Testing and Profiling</h3>
<ul>
<li>Continuous Testing and Profiling: Test your tab component under various conditions and profiles. Use tools like Lighthouse or Web Vitals to track performance metrics and address any issues that may arise.</li>
</ul>
<p>By implementing these strategies, you can elevate your React tab component from merely functional to highly performant, ensuring a smooth user experience across different scenarios and datasets.</p>
<p>Here’s a link to the repository: <a target="_blank" href="https://github.com/Daiveedjay/React-Tab">GitHub</a></p>
<p>And the live version: <a target="_blank" href="https://react-tabbed-component-fcc.netlify.app/">Live Demo</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've successfully built React tabs that are more than just functional – they're optimized for a smooth user experience. From setting up the environment to adding animations, you've covered the essentials.</p>
<p>As you refine and optimize your tabs, remember they play a crucial role in user navigation. Keep coding and may your React tabs deliver a dependable and user-friendly experience.</p>
<p>Happy coding!🌟</p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Avoid Prop Drilling in React ]]>
                </title>
                <description>
                    <![CDATA[ By Ogundiran Ayobami In order to write scalable, reusable, and maintainable applications with React, you'll need to go beyond the surface of using React components, useEffect, useContext, useState, and the like. It involves learning in detail how Rea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/avoid-prop-drilling-in-react/</link>
                <guid isPermaLink="false">66d84e6ac15439a8d5631e54</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React context ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 07 Nov 2023 22:58:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/Purple-Creative-Livestream-YouTube-Thumbnail.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ogundiran Ayobami</p>
<p>In order to write scalable, reusable, and maintainable applications with React, you'll need to go beyond the surface of using React components, useEffect, useContext, useState, and the like. It involves learning in detail how React works in more depth. </p>
<p>And if you don't properly understand these key React concepts, you can run into various issues, like <a target="_blank" href="https://www.quora.com/What-is-prop-drilling-in-ReactJS">prop drilling</a>.</p>
<p>In this tutorial,  you'll learn what prop drilling is. I'll also teach you how to intuitively avoid it without relying on React context. In the end, you'll understand how to identify prop drilling without thinking and fix it with precision.</p>
<p>If you prefer a visual guide, here's a video version of this tutorial on my <a target="_blank" href="https://www.youtube.com/watch?v=ELZZnqHJhlw">YouTube channel here</a> (approximately 15 minutes).</p>
<p><a target="_blank" href="https://www.youtube.com/embed/ELZZnqHJhlw"><img src="https://img.youtube.com/vi/ELZZnqHJhlw/hqdefault.jpg" alt="Watch the video" width="600" height="400" loading="lazy"></a></p>
<h2 id="heading-what-is-prop-drilling">What is Prop Drilling?</h2>
<p>Prop drilling occurs when a parent component generates its state and passes it down as <code>props</code> to its children components that do not consume the props – instead, they only pass it down to another component that finally consumes it. </p>
<p>Below is an example of prop drilling in React:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">ame</span>: <span class="hljs-string">'John'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Content</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Content Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{profile.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>If you check out the example above, you'll notice that <code>profile</code> is passed from the <code>App</code> component through the <code>Header</code> to the <code>Content</code> component, which eventually makes use of the <code>props</code>. This is commonly referred to as prop drilling as the <code>Header</code> component doesn't consume the <code>prop</code> but only passes it down to the <code>Content</code> component that finally consumes it.</p>
<p>Now that you understand what prop drilling is, the next challenge is to figure out how to avoid it because it's not always an intuitive process. </p>
<p>You'll need to start exploring methods to address it. While you can use component composition and React context to resolve it, the challenge lies in not always recognizing the issue until later. </p>
<p>To truly master the art of handling prop drilling intuitively, you must learn how to identify elongated props and contexts.</p>
<h2 id="heading-what-is-an-elongated-prop">What is an Elongated Prop?</h2>
<p><img src="https://images.unsplash.com/photo-1484069560501-87d72b0c3669?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDV8fHF1ZXN0aW9uaW5nfGVufDB8fHx8MTY5OTMyMzQ0MXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Where is the love sung by The Black Eye Peas recreated in a tunnel underpass." width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@emilymorter?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Emily Morter / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>An elongated prop is a <code>prop</code> that is not consumed but it is only passed down to another component. When a component receives a <code>prop</code> from its parent and doesn't consume the <code>prop</code>, it passes the prop down to another component. This prop is called elongated prop because it has been extended.</p>
<p>Whenever you see a <code>prop</code> being passed down by components that neither creates nor consumes the <code>prop</code>, you have an an elongated prop (as well as prop drilling) in your code. The code snippet below is an example:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Profile</span>(<span class="hljs-params">{ user }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">user</span>=<span class="hljs-string">{user}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p><code>user</code>, in this example, is an elongated <code>prop</code> as it is neither created nor consumed by the <code>Profile</code> component. Instead, it is only passed down to the <code>Content</code> component. And that means we have extended <code>user</code> through a component that doesn't need it so that it can get to the one that does.</p>
<p>Now, let's revisit the example we used to illustrate prop drilling. Wait, are you thinking what I'm thinking? The <code>prop</code> that's being passed down in the prop drilling example is indeed an elongated prop, right? Yes, you've got it.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">ame</span>: <span class="hljs-string">'John'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Content</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Content Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{profile.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the code above, you can observe that the <code>prop</code> passed to <code>Header</code> is created in the <code>App</code> component. Then, <code>Header</code> passes it down to its child component named <code>Content</code>. As a result, the <code>profile</code> being passed down can be considered elongated because it is passed through a component (<code>Header</code>) that neither creates nor consumes it down to the one that does.</p>
<p>The <code>Header</code> component passing down the <code>prop</code> it doesn't create or need is unnecessarily stretching the context of the <code>prop</code>. </p>
<p>Now, the question is, how do elongated props help to intuitively avoid prop drilling in React? They make it easy for you to spot <code>props</code> being used where they're are neither created nor consumed.</p>
<p>Rather than focusing on how to solve prop drilling, elongated props enable you to avoid it. This is because it's intuitive to recognize when a component neither creates nor consumes <code>props</code>, and that helps you to know the component is irrelevant.</p>
<p>But before you learn how to quickly avoid prop drilling with your understanding of elongated props, it is important that you know the main causes of prop drilling. Then you'll truly know how to avoid it without thinking about it.</p>
<h2 id="heading-what-causes-prop-drilling">What Causes Prop Drilling?</h2>
<p><img src="https://images.unsplash.com/photo-1617575521317-d2974f3b56d2?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHRyaWdnZXJ8ZW58MHx8fHwxNjk5MzIzNTU2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="»What is your story?«" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@etiennegirardet?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Etienne Girardet / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>Prop drilling doesn't occur out of thin air. It's a consequence of inadequate component organization, and it is not a React problem. It is a thinking or design problem. </p>
<p>You won't encounter an instance of prop drilling without observing one of the following layout mistakes:</p>
<p>First of all, <strong>grouping static elements and dependent components</strong> together to achieve an appealing UI design is the major cause of prop drilling. You can't avoid prop drilling when your UI groups static elements and dependent components together in a parent. The parent component clearly won't use the <code>prop</code>, as everything within it is a static element – except the component that needs a prop.</p>
<p>Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p>In this case, static elements <code>&lt;header&gt; and &lt;h1&gt;</code> are grouped with a dependent component <code>Content</code> – and that's why we have prop drilling therein. </p>
<p>Provided that the <code>Content</code> component is independent or takes no <code>props</code>, it won't need <code>profile</code> and there won't be prop drilling in the first place. This is why forcing a component that should be independent to take <code>props</code> from its parent is a recipe for prop drilling in React.</p>
<p>Second of all, when a <strong>component accepts <code>props</code> that it doesn't use but merely passes it down to its children</strong>, this is a sign that you have prop drilling in your component: </p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span> (<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">"Ayobami"</span>})
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Parent</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/&gt;</span></span>
 ); 
}; 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Parent</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Hero</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Features</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 ); 
};
</code></pre>
<p>In this case there is prop drilling because the <code>Parent</code> component takes <code>profile</code> and it doesn't use it though it passes it down to its children. </p>
<p>Third, when a component that represents an independent section of a page is <strong>forced to take props from its parent</strong>, prop drilling is inevitable. It should ideally be self-contained with its state and operations. </p>
<p>The exception would be if it's intentionally tied to its parent for specific reasons. In such cases, prop drilling becomes a necessary trade-off.  </p>
<p>If you revisit the example of prop drilling cited in this article, you will realize it has a prop drilling issue because the <code>Content</code> component which could have been an independent component by having a state is forced to receive props from its parent.</p>
<p>And finally, <strong>the presence of elongated <code>props</code></strong> is a sure sign of prop drilling. Since an elongated prop is a fundamental element that's consistently present in every case of prop drilling, grasping this concept allows you to instinctively avoid prop drilling. </p>
<p>When you spot an elongated prop, you can be certain that one of the other three mistakes is also in play. In short, an elongated prop is a prop that is not consumed and is also passed down to another component.</p>
<p>So grouping static elements with dependent components, forcing components to take props, elongated props, and receiving a prop without consuming it are the signs to recognize prop drilling in React.</p>
<h2 id="heading-how-to-fix-prop-drilling-with-component-composition">How to Fix Prop Drilling with Component Composition</h2>
<p>Component composition is a good approach to fix prop drilling. If you ever find yourself in a situation where a component passes down a prop it neither creates nor consumes, you can use component composition to fix it. </p>
<p>But to use component composition, you need to understand a component context.</p>
<h3 id="heading-what-is-a-component-context">What is a component context?                           ‌</h3>
<p>The context of a component encompasses everything that is visible within it, including state, props, and children. The following code further illustrates this concept:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">'Ayobami'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In this scenario, the context of <code>App</code> refers to everything we can see within the <code>App</code> component – including the <code>profile</code> prop, the <code>Header</code>, and other <code>App</code> content. Therefore, any data created in the <code>App</code> component should ideally be utilized within the <code>App</code> component itself, either as its own data or as <code>props</code> to its children.</p>
<p>Prop drilling always emerges when the children receiving the <code>props</code> doesn't consume it but only passes it down to its children.  </p>
<p>To avoid prop drilling in this case, any grandchildren components that require access to the same <code>props</code>, especially when their parent don't consume the data, should be passed as children ensuring that the data remains within the <code>App</code> context.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">'Ayobami'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span>&gt;</span> 
        <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
      <span class="hljs-tag">&lt;/<span class="hljs-name">Header</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p><strong><code>Or</code></strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">'Ayobami'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">children</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span>} &gt; 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> 
  ); 
}</span>
</code></pre>
<p>As you can see, we have resolved the prop drilling issue in the previous example, even though we still have a redundant component, <code>&lt;Header&gt;</code>, right? We've successfully addressed prop drilling through component composition. </p>
<p>This process is quite straightforward because we concentrate on recognizing elongated props and repositioning them within appropriate contexts.</p>
<p>The concept of prop drilling is problem-focused, but prop elongation is solution-driven. When dealing with elongated props, our primary goal is to identify props that are not consumed but only passed down to another components.</p>
<h2 id="heading-how-to-fix-prop-drilling-by-moving-state-to-the-consumer">How to Fix Prop Drilling by Moving State to the Consumer</h2>
<p>Prop drilling can also be fixed by moving state to where it is consumed. The example of prop drilling in this article has a component named <code>Content</code>. But the component is forced to receive a <code>prop</code> from its parent instead of having a state and be an independent component – and so we have prop drilling. </p>
<p>We can fix the prop drilling in this case by moving the profile state to where it is consumed.</p>
<p>Let's revisit the example:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">ame</span>: <span class="hljs-string">'John'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Content</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Content Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{profile.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We can fix prop drilling in this case by moving <code>profile</code> to where it is consumed:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
} 

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Content</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">ame</span>: <span class="hljs-string">'John'</span>});
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Content Component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{profile.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p>Now that we have lifted the profile to the <code>Content</code> component where it is consumed, the <code>App</code> component doesn't have a state, while the <code>Header</code> component doesn't receive a prop again as the <code>Content</code> component has its state.</p>
<p>But wait! There is a problem. The <code>Footer</code> component needs the state we moved away from <code>App</code>. There you are! That is the problem with lifting or moving state to where we think it is needed. In this case, if the <code>Footer</code> component doesn't need it, we won't have any issue – but <code>Footer</code> also needs the prop. </p>
<p>Now that <code>Footer</code> needs <code>profile</code> as a prop, we need to solve prop drilling with another method.</p>
<h2 id="heading-how-to-fix-prop-drilling-with-a-children-replacing-parent-strategy">How to Fix Prop Drilling with a Children-Replacing-Parent Strategy</h2>
<p>Earlier in this article, we talked about how to use component composition and moving state to its consumer to solve prop drilling. But as you saw, they have some issues – duplicated components or states.</p>
<p>But using this children-replacing-parent approach fixes the problem effectively:</p>
<p><strong>Working but could be better:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">'Ayobami'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span>&gt;</span> 
        <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
      <span class="hljs-tag">&lt;/<span class="hljs-name">Header</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  ); 
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Header</span>(<span class="hljs-params">{ profile }</span>) </span>{ 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p>The example above shows a solution to the prop drilling example in this article. But as you can see, it has a redundant component, as <code>Header</code> does nothing.</p>
<p><strong>Here's a </strong>better version:<em>**</em></p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{ 
  <span class="hljs-keyword">const</span> [profile, setProfile] = useState({<span class="hljs-attr">name</span>: <span class="hljs-string">'Ayobami'</span>}); 
  <span class="hljs-keyword">return</span> ( 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is the header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">profile</span>=<span class="hljs-string">{profile}</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span> 
  ); 
}
</code></pre>
<p>In the above code, we enhance the component composition solution we previously implemented for the prop drilling example by replacing the redundant <code>Header</code> component with its content in its parent (<code>App</code>).</p>
<h2 id="heading-what-to-avoid">What to Avoid</h2>
<p><img src="https://images.unsplash.com/photo-1587065915399-8f8c714ab540?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEwfHxkYW5nZXJ8ZW58MHx8fHwxNjk5MzIzMDgxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@edwinhooper?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Edwin Hooper / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>It's essential to highlight what to avoid when dealing with prop drilling to prevent unnecessary challenges.</p>
<ul>
<li><strong>Avoid React Context, if possible, to fix prop drilling.</strong> This approach ties your component to a specific context, restricting its usability outside of that context and hindering composition and reusability.</li>
<li><strong>Steer clear of redundant components by employing a children-parent replacement approach.</strong> This approach naturally incorporates <a target="_blank" href="https://www.codementor.io/@dinerismail/the-power-of-component-composition-in-react-21goassg4m">component composition</a> without introducing redundant components or states when resolving prop drilling.</li>
</ul>
<p>By avoiding elongated props, you pave the way for crafting maintainable, high-performing, reusable, and scalable React components. It simplifies the process of lifting states and components by removing the struggle of deciding where to place them. </p>
<p>With your understanding of elongated props, you can confidently position props and components within the right context without undue stress.</p>
<p>In short, you can now discover prop drilling intuitively by paying attention to any component that takes <code>props</code> it doesn't consume and only passes it down to another component. </p>
<p>Thanks for reading – cheers!</p>
<p>Hey wait! I am <a target="_blank" href="https://twitter.com/codingnninja">Ayobami Ogundiran</a> and I am about to start showing how to build your own React, Redux, TypeScript, Zod or Ecommerce websites on my YouTube channel. <a target="_blank" href="https://youtube.com/youtoocancode">Click to subscribe</a> to stay connected. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Components that Work in Any Framework ]]>
                </title>
                <description>
                    <![CDATA[ The browser has a built-in way of writing reusable components in the form of web components. They’re an excellent choice for building interactive and reusable components that work in any frontend framework.  With that said, writing highly interactive... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/write-components-that-work-in-any-framework/</link>
                <guid isPermaLink="false">66bb8e07bec1b237336e9685</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Andrico Karoulla ]]>
                </dc:creator>
                <pubDate>Mon, 06 Nov 2023 20:25:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/og-button.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The browser has a built-in way of writing reusable components in the form of <strong>web components</strong>. They’re an excellent choice for building interactive and reusable components that work in any frontend framework. </p>
<p>With that said, writing highly interactive and robust web components isn’t simple. They require a lot of boilerplate and feel much less intuitive than the components you may have written in frameworks like React, Svelte, or Vue.</p>
<p>In this tutorial, I’ll give you an example of an interactive component written as a web component, and then refactor it using a library that softens the edges and removes heaps of boilerplate.</p>
<p>Don’t sweat it if you’re not familiar with web components. In the next section, I’ll do a (brief) overview of what web components are, and what they’re made out of. If you have some basic experience with them, you can skip the next section.</p>
<h2 id="heading-what-are-web-components">What are Web Components?</h2>
<p>Before web components, the browser didn’t have a standard way of writing reusable components. Many libraries solve this problem, but they often run into limitations like performance, interoperability, and issues with web standards.</p>
<p>Web components are a technology made up of 3 different browser features:</p>
<ul>
<li>Custom elements</li>
<li>Shadow DOM</li>
<li>HTML Templates</li>
</ul>
<p>We’ll do a quick crash course covering these technologies, but it’s by no means a comprehensive breakdown.</p>
<h3 id="heading-what-are-custom-elements">What are Custom Elements?</h3>
<p>With Custom Elements you can author your own custom HTML elements that you can reuse across your site. They can be as simple as text, images, or visual decorations. You can push them further and build interactive components, complex widgets, or entire web applications.</p>
<p>You’re not just limited to using them in your projects, but you can publish them and allow other developers to use them on their sites.</p>
<p>Here are some of the reusable components from my library <a target="_blank" href="https://a2000-docs.netlify.app/">A2K</a>. You can see that they come in all shapes and sizes, and have a range of different functionalities. Using them in your projects is similar to using any old HTML element.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/web-components.png" alt="A small collection of web components from the A2K library" width="600" height="400" loading="lazy">
<em>A small collection of web components from the A2K library</em></p>
<p>Here’s how you’d use the progress element in your project:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Quick Start<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Use web components in your HTML like regular built-in elements. --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a2k-progress</span> <span class="hljs-attr">progress</span>=<span class="hljs-string">"50"</span> /&gt;</span>

        <span class="hljs-comment">&lt;!-- a2k web components use standard JavaScript modules. --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
            <span class="hljs-keyword">import</span> <span class="hljs-string">'https://cdn.jsdelivr.net/npm/@a2000/progress@0.0.5/lib/src/a2k-progress.js'</span>;
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Once you’ve imported the third-party scripts, you can start using the component, <code>a2k-progress</code> in this case, just like any other HTML element.</p>
<p>If you’re building your own web components, there’s virtually no limit to how complex you can make your custom elements. </p>
<p>I recently created a web component that renders a CodeSandbox code editor in the browser. And because it’s a web component, you can use it in any framework you like! If you’d like to learn a little more about that, <a target="_blank" href="https://component-odyssey.com/articles/00-sandpack-lit-universal">you can read more here</a>.</p>
<h3 id="heading-what-is-the-shadow-dom">What is the Shadow DOM?</h3>
<p>If you have a working knowledge of CSS, you’ll know that vanilla CSS is scoped globally. Writing something like this in your global.css:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: tomato;
}
</code></pre>
<p>will give all <code>p</code> elements a nice orange/red color, assuming that no other, more specific CSS selectors are applied to a <code>p</code> element.</p>
<p>Take this select menu, for example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/a2k-select-menu.png" alt="A select menu component with a visual design reminiscent of the old Windows operating systems" width="600" height="400" loading="lazy"></p>
<p>It has a distinct character which is driven by the visual design. You might want to use this component, but if your global styles affect things like the font family, the color, or the font size, it could cause issues with the appearance of the component:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
        <span class="hljs-selector-tag">body</span> {
            <span class="hljs-attribute">color</span>: blue;
            <span class="hljs-attribute">font-size</span>: <span class="hljs-number">12px</span>;
            <span class="hljs-attribute">font-family</span>: system-ui;
        }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a2k-select</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a2k-select</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/a2k-select-menu-2.png" alt="The same select menu, but with a lot of its defining characteristics overridden by global CSS." width="600" height="400" loading="lazy"></p>
<p>This is where the Shadow DOM comes in. The Shadow DOM is an encapsulation mechanism that prevents the rest of the DOM from interfering with your web components. It ensures that the global styles of the web application don’t interfere with any components that you consume. It also means that component library developers can author their components with the confidence that they’ll look and behave as expected across different web applications.</p>
<p>There’s a lot more nuance when it comes to the Shadow DOM, as well as other features that we’re not going to touch on in this article. If you’d like to learn more about web components though, I have an entire course (<a target="_blank" href="https://component-odyssey.com/">Component Odyssey</a>) dedicated to teaching you how to build reusable components that work in any framework.</p>
<h3 id="heading-html-templates">HTML Templates</h3>
<p>The last feature in our whistle-stop tour of web component features is HTML Templates.</p>
<p>What makes this HTML element different from other elements, is that the browser doesn’t render its content to the page. If you were to write the following HTML you wouldn’t see the text “I’m a header” displayed on the page:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>I'm a header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Instead of being used to render the content directly, the content of the template is designed to be copied. The copied template can then be used to render content to the page. </p>
<p>You can think of the template element much like the template for a 3D print. The template isn’t a physical entity, but it’s used to create real-life clones.</p>
<p>You would then reference the template element in your web component, clone it, and render the clone as the markup for your component.</p>
<p>I won’t spend any more time on these web component features, but you’ve probably already noticed that to write vanilla web components, there are a lot of new browser features that you need to know and understand. </p>
<p>You’ll see in the next section that the mental model for building web components doesn’t feel as streamlined as it does for other component frameworks.</p>
<h2 id="heading-how-to-build-a-basic-web-component">How to Build a Basic Web Component</h2>
<p>Now that we’ve briefly covered the fundamental technologies powering a web component, here’s how to build a <em>hello world</em> component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> template = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'template'</span>);
template.innerHTML = <span class="hljs-string">`&lt;p&gt;Hello World&lt;/p&gt;`</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloWorld</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
    <span class="hljs-keyword">constructor</span>() {
        <span class="hljs-built_in">super</span>();
        <span class="hljs-built_in">this</span>.attachShadow({ <span class="hljs-attr">mode</span>: <span class="hljs-string">'open'</span> });
        <span class="hljs-built_in">this</span>.shadowRoot.append(template.content.cloneNode(<span class="hljs-literal">true</span>));
    }
}

customElements.define(<span class="hljs-string">'hello-world'</span>, HelloWorld);
</code></pre>
<p>This is the most simple component you can write, but there’s already so much going on. For someone completely new to web components, and without the background knowledge I provided above, they’re going to be left with a lot of questions, and a lot of confusion.</p>
<p>For me, there are at least two key reasons why web components can be challenging to write, at least within the context of the hello world examples.</p>
<h3 id="heading-the-markup-is-decoupled-from-the-component-logic">The markup is decoupled from the component logic</h3>
<p>In many frameworks, the markup of the component is often treated as a first-class citizen. It’s often the content that gets returned from the component function, or has direct access to the component’s state, or has built-in utilities to help manipulate markup (like loops, conditionals, and so on).</p>
<p>This isn’t the case for web components. In fact, the markup is often defined outside of the component’s class. There’s also no built-in way for the template to reference the current state of the component. This becomes a cumbersome limitation as the complexity of a component grows.</p>
<p>In the world of frontend, components are designed to help developers reuse markup in several pages. As a result, the markup and the component logic are inextricably linked, and so they should be colocated with one another.</p>
<h3 id="heading-writing-a-web-component-requires-understanding-all-of-its-underlying-technologies">Writing a web component requires understanding all of its underlying technologies</h3>
<p>As we saw above, web components are made up of three technologies. You can also see in the hello world code snippet, that we explicitly need to know and understand these three technologies.</p>
<ol>
<li>We’re creating a <strong>template element</strong> and setting its inner HTML</li>
<li>We’re creating a <strong>shadow root</strong>, and explicitly setting its mode to ‘open’.</li>
<li>We’re cloning our <strong>template</strong> and appending it to our <strong>shadow root</strong></li>
<li>We’re registering a new <strong>custom element</strong> to the document</li>
</ol>
<p>There’s nothing inherently wrong with this, since web components are supposed to be a “lower-level” browser API, making them prime for building abstractions on top of. But for a developer coming from a React or a Svelte background, having to understand these new browser features, and then having to write components with them can feel like too much friction.</p>
<h2 id="heading-more-advanced-web-components">More Advanced Web Components</h2>
<p>Let’s take a look at a more advanced web component, a counter button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/counter-button.png" alt="A simple counter button. There's a clickable button, and some text showing how many times the button has been clicked" width="600" height="400" loading="lazy"></p>
<p>You click the button, and the counter increments.</p>
<p>The following example contains a few extra web component concepts, like lifecycle functions and observable attributes. You don’t need to understand everything going on in the code snippet. This example is really only used to illustrate how much boilerplate is required for the most basic of interactive interfaces, a counter button:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> templateEl = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"template"</span>);

templateEl.innerHTML = <span class="hljs-string">`
&lt;button&gt;Press me!&lt;/button&gt;
&lt;p&gt;You pressed me 0 times.&lt;/p&gt;
`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OdysseyButton</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">super</span>();
    <span class="hljs-built_in">this</span>.attachShadow({ <span class="hljs-attr">mode</span>: <span class="hljs-string">"open"</span> });
    <span class="hljs-built_in">this</span>.shadowRoot.appendChild(templateEl.content.cloneNode(<span class="hljs-literal">true</span>));
    <span class="hljs-built_in">this</span>.button = <span class="hljs-built_in">this</span>.shadowRoot.querySelector(<span class="hljs-string">"button"</span>);
    <span class="hljs-built_in">this</span>.p = <span class="hljs-built_in">this</span>.shadowRoot.querySelector(<span class="hljs-string">"p"</span>);
    <span class="hljs-built_in">this</span>.setAttribute(<span class="hljs-string">"count"</span>, <span class="hljs-string">"0"</span>);
  }

    <span class="hljs-comment">// Note: Web components have lifecycle methods,</span>
  <span class="hljs-comment">// If we're setting event listeners when the component is added to the DOM, it's our job to clean</span>
  <span class="hljs-comment">// them up when it gets removed from the DOM</span>
  connectedCallback() {
    <span class="hljs-built_in">this</span>.button.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-built_in">this</span>.handleClick);
  }

  disconnectedCallback() {
    <span class="hljs-built_in">this</span>.button.removeEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-built_in">this</span>.handleClick);
  }

  <span class="hljs-comment">// Unlike frameworks like React, Web Components don't automatically rerender when a prop (or attribute)</span>
  <span class="hljs-comment">// changes. Instead, we need to explicitly define which attributes we want to observe.</span>
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">get</span> <span class="hljs-title">observedAttributes</span>() {
    <span class="hljs-keyword">return</span> [<span class="hljs-string">"disabled"</span>, <span class="hljs-string">"count"</span>];
  }

  <span class="hljs-comment">// When one of the above attributes changes, this lifecycle method runs, and we can</span>
  <span class="hljs-comment">// react to the new attribute's value accordingly.</span>
  attributeChangedCallback(name, _, newVal) {
    <span class="hljs-keyword">if</span> (name === <span class="hljs-string">"count"</span>) {
      <span class="hljs-built_in">this</span>.p.innerHTML = <span class="hljs-string">`You pressed me <span class="hljs-subst">${newVal}</span> times.`</span>;
    }
    <span class="hljs-keyword">if</span> (name === <span class="hljs-string">"disabled"</span>) {
      <span class="hljs-built_in">this</span>.button.disabled = <span class="hljs-literal">true</span>;
    }
  }

  <span class="hljs-comment">// In HTML, attribute values are always strings. This means that it's our job to</span>
  <span class="hljs-comment">// convert types. You can see below that we're converting a string -&gt; number, and then back to a string</span>
  handleClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> counter = <span class="hljs-built_in">Number</span>(<span class="hljs-built_in">this</span>.getAttribute(<span class="hljs-string">"count"</span>));
    <span class="hljs-built_in">this</span>.setAttribute(<span class="hljs-string">"count"</span>, <span class="hljs-string">`<span class="hljs-subst">${counter + <span class="hljs-number">1</span>}</span>`</span>);
  };
</code></pre>
<p>As web component authors, we need to consider a lot of things:</p>
<ul>
<li>Setting up the shadow DOM</li>
<li>Setting up the HTML templates</li>
<li>Cleaning up event listeners</li>
<li>Defining properties that we want to observe</li>
<li>Reacting to properties when they change</li>
<li>Handling type conversions for attributes</li>
</ul>
<p>And there are still so many other things to consider that I haven’t touched on in this article.</p>
<p>That isn’t to say that web components are bad and that you shouldn’t write them. In fact, I’d argue that you learn so much about the browser platform by building with them. </p>
<p>But I feel that there are better ways to write components if your priority is to write interoperable components in a much more streamlined and ergonomic way.</p>
<h2 id="heading-how-to-write-web-components-with-less-boilerplate">How to Write Web Components with Less Boilerplate</h2>
<p>As I mentioned earlier, there are a lot of tools out there to help make writing web components much easier. </p>
<p>One such tool is called Lit, which is developed by a team at Google. <a target="_blank" href="https://lit.dev/">Lit</a> is a lightweight library designed to make writing web components simple, by removing the need for the boilerplate we’ve already seen above.</p>
<p>As we’ll see, Lit does a lot of heavy lifting under-the-hood to help cut down the total lines of code by nearly half! And because Lit is a wrapper around web components and other native browser features, all your existing knowledge about web components is transferable.</p>
<p>To start seeing how Lit simplifies your web components. Here’s the <strong>hello world</strong> example from earlier, but refactored to use Lit instead of a vanilla web component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { LitElement, html } <span class="hljs-keyword">from</span> <span class="hljs-string">"lit"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloWorld</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{
  render() {
    <span class="hljs-keyword">return</span> html`<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>`</span>;
  }
}<span class="hljs-string">`

customElements.define('hello-world', HelloWorld);</span>
</code></pre>
<p>There’s a lot less boilerplate with the Lit component, and Lit handles the two problems I mentioned earlier, a little bit differently. Let’s see how:</p>
<ol>
<li>The markup is directly defined from within the component class. While you can define your templates outside of the class, it’s common practice to return the template from the <code>render</code> function. This is more in line with the mental model presented in other UI frameworks, where the UI is a function of the state.</li>
<li>Lit also doesn’t require developers to attach the shadow DOM, or create templates and clone template elements. While having an understanding of the underlying web component features will help when developing Lit components, they’re not required for getting started, so the barrier for entry is much lower.</li>
</ol>
<p>So now for the big finale, what does the counter component look like once we’ve migrated it over to Lit?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { LitElement, html } <span class="hljs-keyword">from</span> <span class="hljs-string">"lit"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OdysseyCounter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{
  <span class="hljs-keyword">static</span> properties = {
        <span class="hljs-comment">// We define the component's properties as well as their type.</span>
        <span class="hljs-comment">// These properties will trigger the component to re-render when their values change.</span>
        <span class="hljs-comment">// While they're not the same, you can think of these "properties" as being</span>
        <span class="hljs-comment">// Lit's alternatives to "observed attributes"</span>
        <span class="hljs-comment">// If the value is passed down as an attribute, Lit converts the value</span>
        <span class="hljs-comment">// to the correct type</span>
    <span class="hljs-attr">count</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Number</span> },
    <span class="hljs-attr">disabled</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span> },
  };

  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">super</span>();
        <span class="hljs-comment">// There's no need to create a shadow DOM, clone the template,</span>
        <span class="hljs-comment">// or store references to our DOM nodes.</span>
    <span class="hljs-built_in">this</span>.count = <span class="hljs-number">0</span>;
  }

  onCount() {
    <span class="hljs-built_in">this</span>.count = <span class="hljs-built_in">this</span>.count + <span class="hljs-number">1</span>;
  }

  render() {
        <span class="hljs-comment">// Instead of using the attributeChangedCallback lifecycle, the</span>
        <span class="hljs-comment">// render function has access to all of the component's properties,</span>
        <span class="hljs-comment">// which simplifies the process of manipulating our templates.</span>
    <span class="hljs-keyword">return</span> html`<span class="xml">
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> ?<span class="hljs-attr">disabled</span>=</span></span><span class="hljs-subst">${<span class="hljs-built_in">this</span>.disabled}</span><span class="xml"><span class="hljs-tag"> @<span class="hljs-attr">click</span>=</span></span><span class="hljs-subst">${<span class="hljs-built_in">this</span>.onCount}</span><span class="xml"><span class="hljs-tag">&gt;</span>
        Press me!
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You pressed me </span><span class="hljs-subst">${<span class="hljs-built_in">this</span>.count}</span><span class="xml"> times.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    `</span>;
  }
}<span class="hljs-string">`</span>
</code></pre>
<p>The amount of code we’re writing is cut down by almost half! And this difference becomes more noticeable when creating more complex user interfaces.</p>
<h2 id="heading-why-am-i-going-on-about-lit">Why am I going on about Lit?</h2>
<p>I’m a big believer in web components, but I recognise that the barrier to entry is high for many developers. Writing complex web components requires understanding heaps of browser features and the education around web components isn’t as comprehensive as other technologies, like React or Vue.</p>
<p>This is why I think it’s important to use tools like Lit can make writing performant and interoperable web components much easier. This is great if you want your components to work within any frontend framework.</p>
<p>If you’d like to learn even more, this is the approach I teach in my upcoming course <a target="_blank" href="https://component-odyssey.com/">Component Odyssey</a>. This course is excellent for anyone who wants to understand how to write components that work in any framework. </p>
<p>I do this by covering the absolute basics of web components, before moving on to tools like Lit that simplify the process of writing web components without complicating your development environment. By the end, you’ll learn how to build and publish a component library that works across any frontend framework.</p>
<p>If you want early-bird discount codes for Component Odyssey, then head on <a target="_blank" href="https://component-odyssey.com/subscribe">over to the site to get notified</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Web Component ]]>
                </title>
                <description>
                    <![CDATA[ In 2023, browser support for web components (also known as custom elements) is really good. There's never been a better time to start building your own custom elements. Web components, also known as custom elements, are new HTML elements that you cre... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-your-first-web-component/</link>
                <guid isPermaLink="false">66ba5655bab56b945824000f</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joe Attardi ]]>
                </dc:creator>
                <pubDate>Thu, 19 Oct 2023 20:35:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/pexels-just-another-photography-dude-68725.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In 2023, browser support for web components (also known as custom elements) is really good. There's never been a better time to start building your own custom elements.</p>
<p>Web components, also known as custom elements, are new HTML elements that you create. These elements encapsulate some markup, style, and interactivity. </p>
<p>In this article, you'll learn the basics of web components and create a very simple web component that shows the current date.</p>
<p>This guide is intended as a gentle introduction to the concept, so it won't cover some more advanced aspects such as templates, slots, or shadow DOM. But, these are all powerful building blocks to building components that you should learn as you ramp up your skills.</p>
<h2 id="heading-what-is-a-web-component">What is a Web Component?</h2>
<p>A web component is a custom HTML element that you define, with its own tag name. Think of it as an encapsulated, reusable piece of code. Just like regular HTML elements, web components can accept attributes and you can listen for events.</p>
<p>Web components are a nice way to add some extra functionality to your web app. Since it's a web standard, there's no extra third-party code needed.</p>
<p>A web component can be as simple or complex as you want: it can simply display some text (as the example in this article will be doing), or it can be highly interactive. </p>
<h2 id="heading-web-component-basics">Web Component Basics</h2>
<p>To define a web component, create a class that extends from <code>HTMLElement</code>. This class will contain all of your web component's behavior. After that, you need to register it with the browser by calling <code>customElements.define</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
    <span class="hljs-comment">// component implementation goes here</span>
}

customElements.define(<span class="hljs-string">'my-component'</span>, MyComponent);
</code></pre>
<p>Once you've done this, you can use your component by just adding a <code>&lt;my-component&gt;</code> element to your HTML. That's it! You've just added a web component to your page.</p>
<p>Note that the component name has a hyphen. This is required by the specification, to prevent name clashes with potential future standard HTML elements.</p>
<h3 id="heading-lifecycle-callbacks">Lifecycle callbacks</h3>
<p>Web components have a few lifecycle callbacks. These are functions that the browser calls at different parts of the component's lifecycle. Some of these callbacks are:</p>
<ul>
<li><code>connectedCallback</code>: Called when the element is first added to the DOM</li>
<li><code>disconnectedCallback</code>: Called when the element is removed from the DOM</li>
<li><code>attributeChangedCallback</code>: Called when one of the element's watched attributes change. For an attribute to be watched, you must add it to the component class's static <code>observedAttributes</code> property.</li>
</ul>
<p>For this simple component, you'll only need the <code>connectedCallback</code>. </p>
<h2 id="heading-how-to-create-the-component">How to Create the Component</h2>
<p>In a new JavaScript file, create the component class and add the call to <code>customElements.define</code> as shown above. Here's the first pass at the <code>CurrentDate</code> component:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CurrentDate</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
    <span class="hljs-comment">// The browser calls this method when the element is</span>
    <span class="hljs-comment">// added to the DOM.</span>
    connectedCallback() {
        <span class="hljs-comment">// Create a Date object representing the current date.</span>
        <span class="hljs-keyword">const</span> now = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();

        <span class="hljs-comment">// Format the date to a human-friendly string, and set the</span>
        <span class="hljs-comment">// formatted date as the text content of this element.</span>
        <span class="hljs-built_in">this</span>.textContent = now.toLocaleDateString();
    }
}

<span class="hljs-comment">// Register the CurrentDate component using the tag name &lt;current-date&gt;.</span>
customElements.define(<span class="hljs-string">'current-date'</span>, CurrentDate);
</code></pre>
<p>In the <code>connectedCallback</code>, you are getting the current date and calling <code>toLocaleDateString</code>, which formats the date portion of the <code>Date</code> object in a more human friendly format. For example, in the <code>en-US</code> locale, this would be a format like <code>10/18/2023</code>.</p>
<p>There are no event listeners to clean up here, so there is no need for a <code>disconnectedCallback</code>.</p>
<p>Since <code>CurrentDate</code> extends from <code>HTMLElement</code>, it includes all of its properties and methods. This is why you can use the <code>textContent</code> property like with any other HTML element. This will set the formatted date as the value of a text node inside the <code>&lt;current-date&gt;</code> element.</p>
<h2 id="heading-how-to-use-the-component">How to Use the Component</h2>
<p>Before you use the component, you need to load it using an <code>import</code> statement or a <code>script</code> tag. Here's a simple usage example using a <code>script</code> tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./currentDate.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Today's Date<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
The current date is: <span class="hljs-tag">&lt;<span class="hljs-name">current-date</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">current-date</span>&gt;</span>
</code></pre>
<p>Note that custom elements, even when they have no child content, cannot use the self-closing tag syntax supported by some elements. They must always have an explicit closing tag.</p>
<h2 id="heading-future-enhancements">Future Enhancements</h2>
<p>Here are some ways you can enhance the <code>CurrentDate</code> component:</p>
<ul>
<li>Use <code>Intl.DateTimeFormat</code> to create a more human-readable format for the date. You could even add attributes to customize the date format used.</li>
<li>Add support for a <code>date</code> attribute and adapt the component so that it can display any arbitrary date, not just the current date. Of course, in this case, you'll want to change the name from <code>CurrentDate</code> to something else like <code>FormattedDate</code>.</li>
<li>Use the HTML <code>time</code> element inside the component to produce more semantic markup</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you took your first step into the world of web components. </p>
<p>Web components have no third party dependencies, so using them won't have a big impact on your bundle size. But for more complex components, you may want to reach for a library like Svelte or Lit.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use React Components – Props, Default Props, and PropTypes Explained ]]>
                </title>
                <description>
                    <![CDATA[ If you're curious about web development, you've probably heard the buzz about React. React is an open-source JavaScript library used for building user interfaces (UIs) in web applications. It has taken the web development world by storm. One of the k... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-react-components/</link>
                <guid isPermaLink="false">66d45e02182810487e0ce125</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Casmir Onyekani ]]>
                </dc:creator>
                <pubDate>Tue, 05 Sep 2023 22:21:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/React-compo-2-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're curious about web development, you've probably heard the buzz about React.</p>
<p>React is an open-source JavaScript library used for building user interfaces (UIs) in web applications. It has taken the web development world by storm.</p>
<p>One of the key concepts in React is <strong>components.</strong> In this tutorial, we'll explore what React components are, how to pass and render data to them using props, and how to enhance their reliability using default props and propTypes.</p>
<h2 id="heading-what-are-react-components">What Are React Components?</h2>
<p>Imagine you're building a digital LEGO masterpiece. Each individual LEGO brick serves a purpose, but it's only when they're combined that something truly amazing takes shape.</p>
<p>In a similar way, React components are like those LEGO bricks. They are the individual building blocks that come together to create a full-fledged user interface. A component can be a button, a form, a header, or any other part of the webpage that you can think of.</p>
<p>Think of components as reusable templates that you can place throughout your web application to construct a complete user experience.</p>
<h2 id="heading-why-are-components-important-in-react">Why are Components Important in React?</h2>
<p>So, why are components such a big deal in React? There are a few reasons:</p>
<h3 id="heading-modularity-and-reusability">Modularity and Reusability</h3>
<p>By breaking down your UI into components, you create a modular structure. This means you can develop, test, and maintain each piece of your app separately. Plus, once you've created a component, you can reuse it throughout your app, saving you time and effort.</p>
<h3 id="heading-efficiency-in-development">Efficiency in Development</h3>
<p>Components encourage a more efficient development process. You can have different team members working on different components simultaneously without stepping on each other's toes. This speeds up the development process and encourages collaboration.</p>
<h3 id="heading-maintainability">Maintainability</h3>
<p>Imagine you need to update the styling of a button that appears in multiple places in your app. With components, you only need to update the styling in one place, the button's component, and it will automatically reflect wherever it's used.</p>
<h2 id="heading-types-of-react-components">Types of React Components</h2>
<p>There are two main types of components in React: functional components and class components.</p>
<h3 id="heading-how-to-use-functional-components">How to use functional components</h3>
<p>This is the simplest way to define components in React. They are basically JavaScript functions that take in <strong>props</strong> (input data) and return <strong>JSX</strong> (JavaScript Syntax Extension) elements.</p>
<p>Here's a code example to show you how they work:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>; <span class="hljs-comment">// Imports the React library.</span>

<span class="hljs-comment">// Define a functional component named "Button"</span>
<span class="hljs-keyword">const</span> Button = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
      Click Me
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Button; <span class="hljs-comment">// Exports the Button component to make it accessible.</span>
</code></pre>
<p>In this example, we've defined a component called <code>Button</code> using a JavaScript function. This component returns a button element with the text "Click Me".</p>
<h3 id="heading-how-to-use-class-components">How to use class components</h3>
<p>These are JavaScript classes that extend the <strong>React.Component</strong> class.<br>They use ES6 classes and provide more advanced features, such as state management and lifecycle methods.</p>
<p>Here's a code example:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>; <span class="hljs-comment">// Create class-based React components.</span>

<span class="hljs-comment">// Class component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> };
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {this.state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> this.setState({ count: this.state.count + 1 })}&gt;
          Increment
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Counter; <span class="hljs-comment">// Exports the Counter component to make it accessible.</span>
</code></pre>
<p>In this example, the <code>Counter</code> is a class component that maintains a <code>count</code> in its state and updates it when the button is clicked.</p>
<h3 id="heading-functional-components-vs-class-components-when-to-use-each">Functional components vs class components – when to use each</h3>
<p>Looking at the above two code snippets, you can differentiate them base on a few factors.</p>
<ul>
<li><p>Syntax: functional component are less verbose and easier to read due to their concise syntax. Class components are more verbose due to the class structure and the need to bind event handlers in the constructor.</p>
</li>
<li><p>State: until the introduction of <a target="_blank" href="https://www.freecodecamp.org/news/full-guide-to-react-hooks/">hooks</a>, functional components couldn't hold <a target="_blank" href="https://www.freecodecamp.org/news/react-state/#:~:text=In%20our%20React%20app%2C%20once,similarly%20to%20regular%20JavaScript%20functions.">State</a>. With hooks, you can now use the <strong>useState</strong> hook to manage state in functional components. Class component can hold state using the <code>this.state</code> property. State updates are done using <code>this.setState()</code>.</p>
</li>
<li><p>Lifecycle: functional components don't have lifecycle methods. Hooks like <strong>useEffect</strong> can be used to achieve similar effects. Class components support various <a target="_blank" href="https://www.freecodecamp.org/news/react-component-lifecycle-methods/">Lifecycle Methods</a> like <code>componentDidMount</code>, <code>componentDidUpdate</code>, <code>componentWillUnmount</code>, and so on.</p>
</li>
<li><p>Performance: functional components perform better as they don't need extra work required for creating classes. Class component can be a bit slower because of the extra work required for creating classes.</p>
</li>
<li><p>Recommended Use: functional components are preferred for most use cases in modern React development due to their simplicity and functional nature. Class components are still relevant for more complex scenarios that require state management and lifecycle methods (though hooks have made class components less necessary).</p>
</li>
</ul>
<p>React is continually evolving, and new patterns and features might emerge. Stay updated with the latest React documentation and best practices.</p>
<h2 id="heading-how-to-pass-data-to-components-using-props">How to Pass Data to Components using Props</h2>
<p>Props (properties) are like instructions you give to your components. They allow you to pass data from a parent component to a child component. This way, you can customize how components appear and behave.</p>
<p>In simple terms, props are like the parameters that you pass to a function. You can use props to customize the content and behavior of a component based on the values you provide when you use or render that component.</p>
<p>Here's a code example to show you how they work:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ParentComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./ChildComponent'</span>;

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Cas"</span> /&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<pre><code class="lang-jsx"><span class="hljs-comment">// ChildComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello, {props.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChildComponent;
</code></pre>
<p>In this example, the <code>ParentComponent</code> passes the <code>name</code> prop to <code>ChildComponent</code>, which displays a personalized greeting, Hello, Cas!.</p>
<h3 id="heading-how-to-render-with-props">How to render with props</h3>
<p>Rendering with props allows you to create flexible and interactive user interfaces by passing and customizing data within your components. Once you have access to the data within the child component, you can use it to render dynamic content within the component's JSX. This means you can display different UI elements based on the values of the props.</p>
<p>In the <code>ParentComponent</code> used above, you can pass different values to the <code>name</code> prop to customize the displayed message.</p>
<p>Here's a code example:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ParentComponent.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ChildComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./ChildComponent'</span>;

<span class="hljs-keyword">const</span> ParentComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Cas"</span> /&gt;</span>;
<span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Nuel"</span> /&gt;</span>;
<span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Abbey"</span> /&gt;</span>;
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ParentComponent;
</code></pre>
<p>In this example, different values are provided for the <code>name</code> prop. The displayed messages will be:</p>
<ul>
<li><p><code>Hello, Cas!</code></p>
</li>
<li><p><code>Hello, Nuel!</code></p>
</li>
<li><p><code>Hello, Abbey!</code></p>
</li>
</ul>
<h3 id="heading-what-is-dynamic-rendering">What is dynamic rendering?</h3>
<p>Rendering with props becomes powerful when combined with JavaScript expressions. You can use props along with other variables, functions, or logic to render dynamic content. This flexibility enables you to create versatile and interactive user interfaces.</p>
<p>Here's a code example to show you how this works:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Product = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: ${props.price}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      {props.isOnSale &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>On Sale!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Product;
</code></pre>
<p>In this example, the <code>Product</code> component takes multiple props to render details about a product, including its name, price, and whether it's on sale.<br>The expression <code>{props.isOnSale &amp;&amp; &lt;p&gt;On Sale!&lt;/p&gt;}</code> conditionally renders the "On Sale!" message if the <code>isOnSale</code> prop is true.</p>
<h3 id="heading-what-are-default-props">What are default props?</h3>
<p>In some cases, you might want to provide default values for props in case they aren't explicitly passed. This ensures your component doesn't break due to missing data.</p>
<p>Here's a code example:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello, {props.name}!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
};

ChildComponent.defaultProps = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">"Guest"</span>,
};
</code></pre>
<p>In this example, if a value is not provided for the <code>name</code> property, it uses its default value of "Guest".</p>
<h3 id="heading-how-to-use-proptypes">How to use PropTypes</h3>
<p>To maintain the integrity of your application, you can specify the expected types for your props using propTypes.</p>
<p>Here's a code example:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">'prop-types'</span>;

ChildComponent.propTypes = {
  <span class="hljs-attr">name</span>: PropTypes.string.isRequired,
};
</code></pre>
<p>In this example, if the string is not provided for the property value, it will throw an error message.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Understanding the differences between functional and class components is crucial. Functional components, with their cleaner syntax and use of hooks, are favored for most use cases. Class components remain relevant for complex scenarios demanding state management and lifecycle methods.</p>
<p>Components thrive on the principle of passing data via props. Props are akin to instructions, allowing customization of component content and behavior. The capability to render with props enables dynamic and personalized user interfaces. When used in conjunction with JavaScript expressions, props enable versatile and interactive UIs.</p>
<p>Default props and PropTypes are additional tools that enhance component reliability. Default props provide fallback values to prevent breakage due to missing data, while PropTypes enforce data type validation, bolstering application integrity.</p>
<p>As React continues to evolve, staying updated with the latest documentation and best practices is essential. With the knowledge of components, props, default props, and PropTypes, you're well-equipped to embark on your React journey.</p>
<p>Interested in learning more about React? <a target="_blank" href="https://www.freecodecamp.org/news/react-beginner-handbook/#howmuchjavascriptyouneedtoknowtousereact">React for Beginners</a> covers nearly every aspect of React. I recommend it for a deeper insight.</p>
<p>If you found this guide helpful and enjoyable, please give it a like. For more insightful tutorials, follow me on <a target="_blank" href="https://twitter.com/casweb_dev">X</a> for updates 🙏.</p>
<p>Enjoy your coding!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
