<?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[ Timothy Olanrewaju - 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[ Timothy Olanrewaju - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:29:41 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/SmoothTech/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Real-Time Public Speaking and Presentation Coach ]]>
                </title>
                <description>
                    <![CDATA[ Nowadays, being able to present an idea, project, or achievement is a must-have skill. The ability to showcase and talk about your work can determine whether you’re getting that degree, funding, or approval. But while effective communication is impor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-real-time-public-speaking-and-presentation-coach/</link>
                <guid isPermaLink="false">698cfe9129ecd244747b71f1</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Wed, 11 Feb 2026 22:11:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770847484536/70b63767-cc74-4628-a4d1-6bd8c38a5a0c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Nowadays, being able to present an idea, project, or achievement is a must-have skill. The ability to showcase and talk about your work can determine whether you’re getting that degree, funding, or approval.</p>
<p>But while effective communication is important, it’s not a skill everyone possesses. It’s something you build through consistent practice.</p>
<p>Therein lies the challenge: when practicing on our own, it’s easy to overlook composure, posture, and delivery, which are just as important as the speech itself.</p>
<p>That’s where we need a coach. They’re a second pair of eyes and ears that takes note of crucial details and relays them to you while you present. Thanks to recent advancements in visual AI, you can now receive continuous and objective feedback at any time. Frameworks like <a target="_blank" href="https://github.com/GetStream/Vision-Agents">Vision Agents</a> allow you to connect powerful visual models seamlessly and build your desired AI-powered applications.</p>
<p>In this article, we’ll build a real-time public speaking and presentation coach powered by Vision Agents, which you can run on your PC or Mac to practice and improve your delivery.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-well-be-building">​What We’ll Be Building</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-technical-prerequisites">Technical Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-technologies">Key Technologies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-set-up-yolo">Set Up YOLO</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-coaching-instructions">Coaching Instructions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-presentation-agent">The Presentation Agent</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-well-be-building">​What We’ll Be Building</h2>
<p>In this guide, we’ll be walking through how to build a coaching agent that acts as your personal practice companion. This agent will provide real-time feedback, highlighting areas for improvement and offering helpful tips via audio and text.</p>
<p>They’ll track several aspects of your presentation, looking out for:</p>
<ul>
<li><p><strong>Filler words</strong>: to help you reduce the use of words such as “um”, “uh”, “like” and “you know”.</p>
</li>
<li><p><strong>Speaking pace</strong>: to identify whether you’re talking too fast or too slow.</p>
</li>
<li><p><strong>Vocal variety</strong>: to point out if you’re sounding monotonous.</p>
</li>
<li><p><strong>Clarity</strong>: to listen to whether your words are clear enough.</p>
</li>
<li><p><strong>Posture</strong>: to check if you’re maintaining good or bad body posture. Look out for your shoulders, back and chin.</p>
</li>
<li><p><strong>Hand gestures</strong>: to monitor the use of your hands.</p>
</li>
<li><p><strong>Eye contact</strong>: to track whether your eyes are directly looking at your audience.</p>
</li>
</ul>
<p>You now have a mental picture of what we’re setting out to build.</p>
<p>Better still, here’s a visual look at how this coach looks and works.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/C7ijn8Pmhbw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>You can find all the code in this tutorial in this <a target="_blank" href="https://github.com/TimothyOlanrewaju/Public-Speaking-and-Presentation-Coach">repo</a>.</p>
<h2 id="heading-technical-prerequisites">Technical Prerequisites</h2>
<p>Before we begin, ensure you have:</p>
<ul>
<li><p>A <a target="_blank" href="https://getstream.io/accounts/login/">free Stream account</a>.</p>
</li>
<li><p><a target="_blank" href="https://www.python.org/downloads/">Python</a> installed on your PC.</p>
</li>
<li><p>An <a target="_blank" href="https://platform.openai.com/">OpenAI API Key</a>.</p>
</li>
<li><p>Basic knowledge of Python.</p>
</li>
</ul>
<h2 id="heading-key-technologies">Key Technologies</h2>
<p>First, let's introduce the major players in our presentation coach implementation and their respective roles.</p>
<h3 id="heading-stream-video">Stream Video</h3>
<p><a target="_blank" href="https://getstream.io/video/">Stream Video</a> is a complete video infrastructure built on WebRTC, enabling browsers and apps to send live audio and video. It comes supercharged with a global edge network that routes your video to the closest server in under 30 milliseconds. This means that for our presentation coach, the AI can join your practice session like a real participant, seeing and hearing you in real-time with no lag while also providing feedback.</p>
<h3 id="heading-vision-agents">​Vision Agents</h3>
<p><a target="_blank" href="https://visionagents.ai/">Vision Agents</a> is an open-source framework from Stream that allows you to connect video streams, AI models, and chat interfaces. It ships with Stream Video as its default transport layer.</p>
<p>This framework simplifies the development of multimodal AI agentic applications by providing a unified Agent class that orchestrates everything. With Vision Agents, you can connect models and also get them to work together seamlessly as one coordinated system.</p>
<h3 id="heading-openai-realtime-api">OpenAI RealTime API</h3>
<p><a target="_blank" href="https://visionagents.ai/integrations/openai">OpenAI RealTime API</a> allows you to stream live, low-latency interactions with OpenAI models. Its strength lies in its ability to handle speech-to-speech in one go. Your words go in, the AI thinks about them, and you get audio and text feedback almost instantaneously. Your app and model can communicate instantly, just like a live conversation. This will be the presentation coach’s actual brainbox.</p>
<h3 id="heading-yolo11">YOLO11</h3>
<p><a target="_blank" href="https://docs.ultralytics.com/">YOLO11</a> is a modern and powerful computer vision model developed by Ultralytics. It supports a wide range of tasks, including object detection, instance segmentation, image classification, pose estimation/keypoint detection, and oriented bounding box detection.</p>
<p>It tracks 17 different points on your body, such as your shoulders, head, and hand positions, and also attempts to determine your posture at specific times. Our presentation coach will focus on the aspects of pose estimation and keypoint detection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770651953726/77a8feee-3fd9-46dd-90a5-da6527f1ecac.png" alt="Real-time AI presentation coach pipeline combining live video pose detection and speech transcription to deliver voice and text feedback." class="image--center mx-auto" width="1024" height="768" loading="lazy"></p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Now, let's get straight into building this presentation coach with all the technologies we’ve highlighted.</p>
<p>We’ll start bu installing uv, which is the recommended installer for Vision Agents. Create a project folder and run this command in the terminal if you’re using pip installer:</p>
<pre><code class="lang-python">pip install uv
</code></pre>
<p>For Linux/MacOS, run:</p>
<pre><code class="lang-python">curl -LsSf https://astral.sh/uv/install.sh | sh.
</code></pre>
<p>For Windows, run:</p>
<pre><code class="lang-powershell">powershell <span class="hljs-literal">-ExecutionPolicy</span> ByPass <span class="hljs-literal">-c</span> \<span class="hljs-string">"irm https://astral.sh/uv/install.ps1 | iex\"</span>
</code></pre>
<p>Next, initialize uv in your project:</p>
<pre><code class="lang-python">uv init
</code></pre>
<p>Then create a virtual environment:</p>
<pre><code class="lang-python">uv venv
</code></pre>
<p>And activate the virtual environment:</p>
<pre><code class="lang-python">.venv\Scripts\activate
</code></pre>
<p>Now install <a target="_blank" href="https://github.com/GetStream/Vision-Agents">Vision Agents</a> with the required plugins and dependencies:</p>
<pre><code class="lang-python">uv add vision-agents[getstream,openai,ultralytics] python-dotenv
</code></pre>
<p>In the root directory, create an <strong>.env</strong> file and provide the necessary credentials:</p>
<pre><code class="lang-javascript">STREAM_API_KEY=your-stream-api-key

STREAM_API_SECRET=your-stream-secret

OPENAI_API_KEY=your-openai-api-key

CALL_ID=<span class="hljs-string">"practice-room"</span> <span class="hljs-comment">//feel free to call it any name</span>
</code></pre>
<p>In the root directory, create an <strong>'instructions'</strong> folder and a Markdown file called '<strong>coach.md'</strong> inside it.</p>
<p>In the root directory, create a file and name it <strong>download_yolo_pose.py</strong>.</p>
<p>Your current project folder structure should look like this:</p>
<pre><code class="lang-plaintext">└── 📁Presentation Coach

    └── 📁.venv

    └── 📁instructions

        ├──coach.md

    └── .env

    └── .gitignore

    └── download_yolo_pose.py

    └── main.py

    └── pyproject.toml

    └── README.md

    └── uv.lock
</code></pre>
<h2 id="heading-set-up-yolo">Set Up YOLO</h2>
<p>The Ultralytics YOLO11 framework uses the <strong>yolo11n-pose.pt</strong> model file to watch your posture throughout your presentation. This pre-trained deep learning model file performs pose estimation by detecting keypoints. In your <strong>download_yolo_pose.py</strong> file, insert this:</p>
<pre><code class="lang-python">//download_yolo_pose.py

<span class="hljs-keyword">from</span> ultralytics <span class="hljs-keyword">import</span> YOLO

<span class="hljs-keyword">import</span> shutil

<span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path

model = YOLO(<span class="hljs-string">"yolo11n-pose.pt"</span>)  

project_root = Path(__file__).parent

target = project_root / <span class="hljs-string">"yolo11n-pose.pt"</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> target.exists():

    print(<span class="hljs-string">"Copying model to project root..."</span>)

    shutil.copy2(model.model.path, target)

<span class="hljs-keyword">else</span>:

    print(<span class="hljs-string">"Model already in project root."</span>)

print(<span class="hljs-string">f"Ready: <span class="hljs-subst">{target.resolve()}</span>"</span>)
</code></pre>
<p>This automatically downloads the <strong>yolo11n-pose.pt</strong> file, if absent in your project, and copies it to the project root. </p>
<h2 id="heading-coaching-instructions">Coaching Instructions</h2>
<p>AI plays the role of the coach in this implementation. The <strong>coach.md</strong> file gives it its entire personality, expertise, and coaching philosophy. You specify the tone, output rate, length of response, speaking pace, timing of feedback, and other metrics you want your AI to follow. Without these instructions, you’ll receive generic responses, vague tips, lengthy responses, and interruptions.</p>
<p>Paste this in your <strong>coach.md</strong> file to get the best results:</p>
<pre><code class="lang-markdown">//instructions/coach.md

These instructions describe how the coaching system should behave when someone is practicing a presentation. Ensure to give quick, specific tips and try not to interrupt their flow. Only provide feedback after detecting at least 3-5 seconds of silence.

On format, feedback should appear like short texts on screen and keep them within 1 or 2 sentences maximum.

You want people to be relaxed during the presentation, so, ensure you start with something positive and always add one actionable tip.

You’ll have access to video feeds, transcripts and pose data. That’s enough to get a good idea of pace, body language and how engaged they look.

A big part of your evaluation is to understand their speech. You should look out for:

Pace: Shouldn’t be too fast or too slow. Send a message to address it when noticed.

Filler words: Listen for “um”,”uh”,”emm”,”you know”. If they keep popping up, send a reminder to pause.

Tone and variety: Watch out for their pitch and suggest accordingly

Clarity: Make sure that their words are clear enough

Also, keep an eye on the body posture. Encourage confident presentation involving use of hands, straight shoulders and steady eye contact.
</code></pre>
<h2 id="heading-the-presentation-agent">The Presentation Agent</h2>
<p>Now that we have all our pieces in place, it’s time to look at the Central Processing Unit of our presentation coach. Inside the <strong>main.py</strong> file is where the magic of Vision Agents happens, tying live video streaming, OpenAI Realtime functions, YOLO pose detection, and your coaching instructions into one multimodal agent.</p>
<p>Here’s how our <strong>main.py</strong> looks:</p>
<pre><code class="lang-python">// main.py

<span class="hljs-keyword">import</span> logging

<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> vision_agents.core <span class="hljs-keyword">import</span> Agent, User, cli

<span class="hljs-keyword">from</span> vision_agents.core.agents <span class="hljs-keyword">import</span> AgentLauncher

<span class="hljs-keyword">from</span> vision_agents.plugins <span class="hljs-keyword">import</span> getstream, openai, ultralytics

load_dotenv()

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_agent</span>(<span class="hljs-params">**kwargs</span>) -&gt; Agent:</span>

    agent_user = User(

        name=<span class="hljs-string">"Public Speaking &amp; Presentation Coach"</span>,

        id=<span class="hljs-string">"coach_agent"</span>,

        image=<span class="hljs-string">"https://api.dicebear.com/7.x/bottts/svg?seed=coach"</span>

    )

    <span class="hljs-keyword">return</span> Agent(

        edge=getstream.Edge(),

        agent_user=agent_user,

        instructions=<span class="hljs-string">"@instructions/coach.md"</span>,

        llm=openai.Realtime(

            fps=<span class="hljs-number">6</span>,                          

            voice=<span class="hljs-string">"alloy"</span>,

        ),

        processors=[

            ultralytics.YOLOPoseProcessor(model_path=<span class="hljs-string">"yolo11n-pose.pt"</span>)

        ],

    )

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">join_call</span>(<span class="hljs-params">agent: Agent, call_type: str, call_id: str, **kwargs</span>) -&gt; <span class="hljs-keyword">None</span>:</span>

    print(<span class="hljs-string">f"Presentation Coach Agent starting..."</span>)

    print(<span class="hljs-string">f"Joining call: <span class="hljs-subst">{call_type}</span>:<span class="hljs-subst">{call_id}</span>"</span>)

    call = <span class="hljs-keyword">await</span> agent.create_call(call_type, call_id)

    session = <span class="hljs-keyword">await</span> agent.join(call)

    print(<span class="hljs-string">"Agent connected and ready!"</span>)

    print(<span class="hljs-string">"Real-time coaching enabled"</span>)

    <span class="hljs-keyword">try</span>:

        <span class="hljs-keyword">await</span> agent.llm.simple_response(

            text=<span class="hljs-string">"Greet the user warmly and say you're ready to help them practice. "</span>

                 <span class="hljs-string">"Watch their body language and speech — give encouraging, real-time feedback."</span>

        )

        <span class="hljs-keyword">await</span> agent.finish()

    <span class="hljs-keyword">finally</span>:

        <span class="hljs-keyword">await</span> session.close()

<span class="hljs-keyword">if</span> name == <span class="hljs-string">"__main__"</span>:

    cli(AgentLauncher(create_agent=create_agent, join_call=join_call))
</code></pre>
<p>Let’s walk through what’s happening in this code:</p>
<ul>
<li><p>Your keys are loaded from the .env file by the <code>load_dotenv</code> function.</p>
</li>
<li><p>The <code>create_agent</code> function then creates the coach’s identity using the User object, assigning it a name, ID, and avatar.</p>
</li>
<li><p>The instantiated Agent object takes several arguments, which configure how the agent behaves and interacts with video, models, and the user. Our Agent object has the following arguments: <code>edge</code>, <code>agent_user</code>, <code>instructions</code>, <code>LLMS</code>, and <code>processors</code>.</p>
</li>
<li><p><code>edge=getstream.Edge()</code> connects everything to Stream’s global, low-latency video infrastructure.</p>
</li>
<li><p><code>agent_user</code> defines the coach’s identity created earlier.</p>
</li>
<li><p>Instructions load your coaching philosophy located in the coach.md directly into the agent’s brain.</p>
</li>
<li><p><code>llm</code> specifies the AI language model and parameters. For this agent, it is OpenAI.Realtime, which opens a WebSocket to OpenAI’s Realtime API. With a frame rate of 6, the agent receives six video frames per second. The voice parameter set to “alloy” allows for real-time speech generation.</p>
</li>
<li><p><code>processors</code> perform specific types of AI/ML computation on incoming streams. In this case, video frames were analysed by YOLO11.</p>
</li>
<li><p>With the <code>join_call</code> function, the agent joins the call with a short, welcoming greeting that appears instantly in the chat. The <code>await agent.finish</code> function hands control over to the real-time loop of the agent, which continuously listens, watches, thinks, and responds automatically. No need for manual prompts.</p>
</li>
</ul>
<p>To run the agent, enter this on your terminal:</p>
<pre><code class="lang-python">python main.py
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We have successfully developed a public speaking and presentation AI agent that provides timely feedback with valuable tips to help you improve your presentation in real-time.</p>
<p>This was made possible by the trio of Vision Agents, YOLO11, and OpenAI Realtime API. In under 50 lines of code, we were able to build an agent that costs nearly nothing (just a few tokens) compared to paying $99 for a SaaS platform or hiring a physical coach. Pretty cool.</p>
<p>With Vision Agents, you have a developer-friendly framework that opens up numerous opportunities for builders to create engaging AI apps efficiently. </p>
<p>Happy building!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Conversational AI Chatbot with Stream Chat and React ]]>
                </title>
                <description>
                    <![CDATA[ Modern chat applications are increasingly incorporating voice input capabilities because they offer a more engaging and versatile user experience. This also improves accessibility, allowing users with different needs to interact more comfortably with... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-conversational-ai-chatbot-with-stream-chat-and-react/</link>
                <guid isPermaLink="false">6851d017416010d301ffa732</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ chatbot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 17 Jun 2025 20:29:11 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750192110424/b23653af-c2de-4631-973f-dcac3c0bdb41.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Modern chat applications are increasingly incorporating voice input capabilities because they offer a more engaging and versatile user experience. This also improves accessibility, allowing users with different needs to interact more comfortably with such applications. </p>
<p>In this tutorial, I’ll guide you through the process of creating a conversational AI application that integrates real-time chat functionality with voice recognition. By leveraging Stream Chat for robust messaging and the Web Speech API for speech to text conversion, you’ll build a multi-faceted chat application that supports both voice and text interaction.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sneak-peek">Sneak Peek</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-core-technologies">Core Technologies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-backend-implementation-guide">Backend Implementation Guide</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-implementation-guide">Frontend Implementation Guide</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-project-setup-1">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-app-component">Understanding the App Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-adding-ai-to-the-channel">Adding AI to the Channel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configuring-the-channelheader">Configuring the ChannelHeader</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-adding-an-ai-state-indicator">Adding an AI State Indicator</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-building-the-speech-to-text-functionality">Building the Speech to Text Functionality</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-complete-process-flow">Complete Process Flow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we begin, ensure you have the following:</p>
<ul>
<li><p>A Stream account with an API key and secret (Read on how to get them <a target="_blank" href="https://getstream.io/blog/stream-getting-started-guide/">here</a>)</p>
</li>
<li><p>Access to an LLM API (like OpenAI, Anthropic).</p>
</li>
<li><p>Node.js and npm/yarn installed.</p>
</li>
<li><p>Basic knowledge of React and TypeScript.</p>
</li>
<li><p>Modern browser with WebSpeech API support (like Chrome, Edge)</p>
</li>
</ul>
<h2 id="heading-sneak-peek">Sneak Peek</h2>
<p>Let’s take a quick look at the app we’ll be building in this tutorial. This way, you get a feel for what it does before we jump into the details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749925010635/5228ae93-ff56-4b0f-8ea8-c7a160973191.gif" alt="5228ae93-ff56-4b0f-8ea8-c7a160973191" class="image--center mx-auto" width="1200" height="675" loading="lazy"></p>
<p>If you’re now excited, let’s get straight into it!</p>
<h2 id="heading-core-technologies">Core Technologies</h2>
<p>This application is powered by three main players: Stream Chat, the Web Speech API, and a Node.js + Express backend.</p>
<p><a target="_blank" href="https://getstream.io/">Stream Chat</a> is a platform that helps you easily build and integrate rich, real-time chat and messaging experiences into your applications. It offers a variety of SDKs (Software Development Kits) for different platforms (like Android, iOS, React) and pre-built UI components to streamline development. Its robustness and engaging chat functionality make it a great choice for this app – we don’t need to build anything from scratch.</p>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API">Web Speech API</a> is a browser standard that allows you to integrate voice input and output into your apps, enabling features like speech recognition (converting spoken speech to text) and speech synthesis (converting text to speech). We’ll use the speech recognition feature in this project.</p>
<p>The Node.js + Express backend manages correct agent instantiation and processes the conversational responses generated by our LLM API.</p>
<h2 id="heading-backend-implementation-guide">Backend Implementation Guide</h2>
<p>Let’s begin with our backend, the engine room – where user input is routed to the appropriate AI model, and a processed response is returned. Our backend supports multiple AI models, specifically OpenAI and Anthropic.</p>
<h3 id="heading-project-setup">Project Setup</h3>
<ol>
<li><p>Create a folder, call it ‘<strong>My-Chat-Application</strong>’.</p>
</li>
<li><p>Clone this <a target="_blank" href="https://github.com/GetStream/ai-assistant-nodejs.git">Github repository</a></p>
</li>
<li><p>After cloning, rename the folder to ‘<strong>backend</strong>’</p>
</li>
<li><p>Open the <code>.env.example</code> file and provide the necessary keys (you’ll need to provide either the OpenAI or Anthropic key – the Open Weather key is optional).</p>
</li>
<li><p>Rename the <code>env.example</code>file to <code>.env</code></p>
</li>
<li><p>Install dependencies by running this command:</p>
<pre><code class="lang-javascript"> npm install
</code></pre>
</li>
<li><p>Run the project by entering this command:</p>
<pre><code class="lang-javascript"> npm start
</code></pre>
<p> Your backend should be running smoothly on <code>localhost:3000</code>.</p>
</li>
</ol>
<h2 id="heading-frontend-implementation-guide">Frontend Implementation Guide</h2>
<p>This section explores two broad, interrelated components: the chat structure and speech recognition.</p>
<h3 id="heading-project-setup-1">Project Setup</h3>
<p>We will be creating and setting up our React project with the Stream Chat React SDK. We'll use Vite with the TypeScript template. To do that, navigate to your <strong>My-Chat-Application</strong> folder, open your terminal and enter this command:</p>
<pre><code class="lang-javascript">npm create vite frontend -- --template react-ts
cd chat-example
npm i stream-chat stream-chat-react
</code></pre>
<p>With our frontend project set up, we can now run the app:</p>
<pre><code class="lang-javascript">npm run dev
</code></pre>
<h3 id="heading-understanding-the-app-component">Understanding the App Component</h3>
<p>The main focus here is to initialize a chat client, connect a user, create a channel, and render the chat interface. We’ll go through all these processes step by step to help you understand them better:</p>
<h4 id="heading-define-constants">Define Constants</h4>
<p>First, we need to provide some important credentials that we need for user creation and chat client setup. You can find these credentials on your Stream <a target="_blank" href="https://dashboard.getstream.io/">dashboard</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> apiKey = <span class="hljs-string">"xxxxxxxxxxxxx"</span>;
<span class="hljs-keyword">const</span> userId = <span class="hljs-string">"111111111"</span>;
<span class="hljs-keyword">const</span> userName = <span class="hljs-string">"John Doe"</span>;
<span class="hljs-keyword">const</span> userToken = <span class="hljs-string">"xxxxxxxxxx.xxxxxxxxxxxx.xx_xxxxxxx-xxxxx_xxxxxxxx"</span>; <span class="hljs-comment">//your stream secret key</span>
</code></pre>
<blockquote>
<p>Note: These are dummy credentials. Make sure to use your own credentials.</p>
</blockquote>
<h4 id="heading-create-a-user">Create a User</h4>
<p>Next, we need to create a user object. We’ll create it using an ID, name and a generated avatar URL:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> user: User = {
  <span class="hljs-attr">id</span>: userId,
  <span class="hljs-attr">name</span>: userName,
  <span class="hljs-attr">image</span>: <span class="hljs-string">`https://getstream.io/random_png/?name=<span class="hljs-subst">${userName}</span>`</span>,
};
</code></pre>
<h4 id="heading-setup-a-client">Setup a Client</h4>
<p>We need to track the state of the active chat channel using the <code>useState</code> hook to ensure seamless real-time messaging in this Stream Chat application. A custom hook called <code>useCreateChatClient</code> initializes the chat client with an API key, user token, and user data:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [channel, setChannel] = useState&lt;StreamChannel&gt;();
  <span class="hljs-keyword">const</span> client = useCreateChatClient({
    apiKey,
    <span class="hljs-attr">tokenOrProvider</span>: userToken,
    <span class="hljs-attr">userData</span>: user,
  });
</code></pre>
<h4 id="heading-initialize-channel">Initialize Channel</h4>
<p>Now, we initialize a messaging channel to enable real-time communication in the Stream Chat application. When the chat client is ready, the <code>useEffect</code> hook triggers the creation of a messaging channel named <code>my_channel</code>, adding the user as a member. This channel is then stored in the channel state, ensuring that the app is primed for dynamic conversation rendering.</p>
<pre><code class="lang-javascript">  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!client) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> channel = client.channel(<span class="hljs-string">"messaging"</span>, <span class="hljs-string">"my_channel"</span>, {
      <span class="hljs-attr">members</span>: [userId],
    });

    setChannel(channel);
  }, [client]);
</code></pre>
<h4 id="heading-render-chat-interface">Render Chat Interface</h4>
<p>With all the integral parts of our chat application all set up, we’ll return a JSX to define the chat interface's structure and components:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">if</span> (!client) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Setting up client &amp; connection...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Chat</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{client}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Channel</span> <span class="hljs-attr">channel</span>=<span class="hljs-string">{channel}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Window</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MessageList</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MessageInput</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Window</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Thread</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Channel</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Chat</span>&gt;</span></span>
  );
</code></pre>
<p>In this JSX structure:</p>
<ul>
<li><p>If the client is not ready, it displays a "Setting up client &amp; connection..." message.</p>
</li>
<li><p>Once the client is ready, it renders the chat interface using:</p>
<ul>
<li><p><code>&lt;Chat&gt;</code>: Wraps the Stream Chat context with the initialized client.</p>
</li>
<li><p><code>&lt;Channel&gt;</code>: Sets the active channel.</p>
</li>
<li><p><code>&lt;Window&gt;</code>: Contains the main chat UI components:</p>
<ul>
<li><p><code>&lt;MessageList&gt;</code>: Displays the list of messages.</p>
</li>
<li><p><code>&lt;MessageInput&gt;</code>: Uses a custom <code>CustomMessageInput</code> for sending messages.</p>
</li>
</ul>
</li>
<li><p><code>&lt;Thread&gt;</code>: Renders threaded replies.</p>
</li>
</ul>
</li>
</ul>
<p>With this, we've set up our chat interface and channel, and we have a client ready. Here's what our interface looks like so far:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749901280964/4b788065-27ae-40b4-9882-c74bacef0fc4.png" alt="stream chat interface" class="image--center mx-auto" width="1000" height="540" loading="lazy"></p>
<h3 id="heading-adding-ai-to-the-channel">Adding AI to the Channel</h3>
<p>Remember, this chat application is designed to interact with an AI, so we need to be able to both add and remove the AI from the channel. On the UI, we’ll add a button in the channel header to enable users add and remove AI. But we still need to determine whether or not we already have it in the channel to know which option to display.</p>
<p>For that we’ll create a custom hook called <code>useWatchers</code>. It monitors the presence of the AI using a concept called <code>watchers</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useCallback, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Channel } <span class="hljs-keyword">from</span> <span class="hljs-string">'stream-chat'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useWatchers = <span class="hljs-function">(<span class="hljs-params">{ channel }: { channel: Channel }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [watchers, setWatchers] = useState&lt;string[]&gt;([]);
  <span class="hljs-keyword">const</span> [error, setError] = useState&lt;<span class="hljs-built_in">Error</span> | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> queryWatchers = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
    setError(<span class="hljs-literal">null</span>);

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> channel.query({ <span class="hljs-attr">watchers</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">offset</span>: <span class="hljs-number">0</span> } });
      setWatchers(result?.watchers?.map(<span class="hljs-function">(<span class="hljs-params">watcher</span>) =&gt;</span> watcher.id).filter((id): id is string =&gt; id !== <span class="hljs-literal">undefined</span>) || [])
      <span class="hljs-keyword">return</span>;
    } <span class="hljs-keyword">catch</span> (err) {
      setError(err <span class="hljs-keyword">as</span> <span class="hljs-built_in">Error</span>);
    }
  }, [channel]);

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

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> watchingStartListener = channel.on(<span class="hljs-string">'user.watching.start'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> userId = event?.user?.id;
      <span class="hljs-keyword">if</span> (userId &amp;&amp; userId.startsWith(<span class="hljs-string">'ai-bot'</span>)) {
        setWatchers(<span class="hljs-function">(<span class="hljs-params">prevWatchers</span>) =&gt;</span> [
          userId,
          ...(prevWatchers || []).filter(<span class="hljs-function">(<span class="hljs-params">watcherId</span>) =&gt;</span> watcherId !== userId),
        ]);
      }
    });

    <span class="hljs-keyword">const</span> watchingStopListener = channel.on(<span class="hljs-string">'user.watching.stop'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> userId = event?.user?.id;
      <span class="hljs-keyword">if</span> (userId &amp;&amp; userId.startsWith(<span class="hljs-string">'ai-bot'</span>)) {
        setWatchers(<span class="hljs-function">(<span class="hljs-params">prevWatchers</span>) =&gt;</span>
          (prevWatchers || []).filter(<span class="hljs-function">(<span class="hljs-params">watcherId</span>) =&gt;</span> watcherId !== userId)
        );
      }
    });

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      watchingStartListener.unsubscribe();
      watchingStopListener.unsubscribe();
    };
  }, [channel]);

  <span class="hljs-keyword">return</span> { watchers, error };
};
</code></pre>
<h3 id="heading-configuring-the-channelheader">Configuring the ChannelHeader</h3>
<p>We can now build a new channel header component by utilizing the <code>useChannelStateContext</code> hook to access the channel and initialize the custom <code>useWatchers</code> hook. Using the watchers' data, we define an <code>aiInChannel</code> variable to display relevant text. Based on this variable, we invoke either the <code>start-ai-agent</code> or <code>stop-ai-agent</code> endpoint on the Node.js backend.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useChannelStateContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'stream-chat-react'</span>;
<span class="hljs-keyword">import</span> { useWatchers } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useWatchers'</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">ChannelHeader</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { channel } = useChannelStateContext();
  <span class="hljs-keyword">const</span> { watchers } = useWatchers({ channel });

  <span class="hljs-keyword">const</span> aiInChannel =
    (watchers ?? []).filter(<span class="hljs-function">(<span class="hljs-params">watcher</span>) =&gt;</span> watcher.includes(<span class="hljs-string">'ai-bot'</span>)).length &gt; <span class="hljs-number">0</span>;
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'my-channel-header'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{(channel?.data as { name?: string })?.name ?? 'Voice-and-Text AI Chat'}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{addOrRemoveAgent}</span>&gt;</span>
        {aiInChannel ? 'Remove AI' : 'Add AI'}
      <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">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addOrRemoveAgent</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (!channel) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> endpoint = aiInChannel ? <span class="hljs-string">'stop-ai-agent'</span> : <span class="hljs-string">'start-ai-agent'</span>;
    <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://127.0.0.1:3000/<span class="hljs-subst">${endpoint}</span>`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">channel_id</span>: channel.id, <span class="hljs-attr">platform</span>: <span class="hljs-string">'openai'</span> }),
    });
  }
}
</code></pre>
<h3 id="heading-adding-an-ai-state-indicator">Adding an AI State Indicator</h3>
<p>AIs take a bit of time to process information, so while the AI is processing, we add an indicator to reflect its status. We create a <code>AIStateIndicator</code> that does that for us:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { AIState } <span class="hljs-keyword">from</span> <span class="hljs-string">'stream-chat'</span>;
<span class="hljs-keyword">import</span> { useAIState, useChannelStateContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'stream-chat-react'</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">MyAIStateIndicator</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { channel } = useChannelStateContext();
  <span class="hljs-keyword">const</span> { aiState } = useAIState(channel);
  <span class="hljs-keyword">const</span> text = textForState(aiState);
  <span class="hljs-keyword">return</span> text &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'my-ai-state-indicator'</span>&gt;</span>{text}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">textForState</span>(<span class="hljs-params">aiState: AIState</span>): <span class="hljs-title">string</span> </span>{
    <span class="hljs-keyword">switch</span> (aiState) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'AI_STATE_ERROR'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Something went wrong...'</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'AI_STATE_CHECKING_SOURCES'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Checking external resources...'</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'AI_STATE_THINKING'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"I'm currently thinking..."</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'AI_STATE_GENERATING'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Generating an answer for you...'</span>;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>;
    }
  }
}
</code></pre>
<h3 id="heading-building-the-speech-to-text-functionality">Building the Speech to Text Functionality</h3>
<p>Up to this point, we have a functional chat application that sends messages and receives feedback from an AI. Now, we want to enable voice interaction, allowing users to speak to the AI instead of typing manually.</p>
<p>To achieve this, we’ll set up speech-to-text functionality within a <code>CustomMessageInput</code> component. Let’s walk through the entire process, step by step, to understand how to achieve it.</p>
<h4 id="heading-initial-states-configuration">Initial States Configuration</h4>
<p>When the <code>CustomMessageInput</code> component first mounts, it begins by establishing its foundational state structure:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [isRecording, setIsRecording] = useState&lt;boolean&gt;(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [isRecognitionReady, setIsRecognitionReady] = useState&lt;boolean&gt;(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> recognitionRef = useRef&lt;any&gt;(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> isManualStopRef = useRef&lt;boolean&gt;(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> currentTranscriptRef = useRef&lt;string&gt;(<span class="hljs-string">""</span>);
</code></pre>
<p>This initialization step is crucial because it establishes the component's ability to track multiple concurrent states: whether recording is active, whether the speech API is ready, and various persistence mechanisms for managing the speech recognition lifecycle.</p>
<h4 id="heading-context-integration">Context Integration</h4>
<p>In Stream Chat, the <code>MessageInputContext</code> is established within the <code>MessageInput</code> component. It provides data to the Input UI component and its children. Since we want to use the values stored within the <code>MessageInputContext</code> to build our own custom input UI component, we’ll be calling the <code>useMessageInputContext</code> custom hook:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// Access the MessageInput context</span>
  <span class="hljs-keyword">const</span> { handleSubmit, textareaRef } = useMessageInputContext();
</code></pre>
<p>This step ensures that the voice input feature integrates seamlessly with the existing chat infrastructure, sharing the same <code>textarea</code> reference and submission mechanisms that other input methods use.</p>
<h4 id="heading-web-speech-api-detection-and-initialization">Web Speech API Detection and Initialization</h4>
<p>The Web Speech API is not supported by some browsers, which is why we need to check if the browser running this application is compatible. The component's first major process involves detecting and initializing the Web Speech API:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> SpeechRecognition = (<span class="hljs-built_in">window</span> <span class="hljs-keyword">as</span> any).SpeechRecognition||(<span class="hljs-built_in">window</span> <span class="hljs-keyword">as</span> any).webkitSpeechRecognition;
</code></pre>
<p>Once the API is detected, the component configures the speech recognition service with optimal settings.</p>
<h4 id="heading-event-handler-configuration">Event Handler Configuration</h4>
<p>We’ll have two event handlers: the result processing handler and the lifecycle event handler.</p>
<p>The result processing handler processes speech recognition output. It demonstrates a two-phase processing approach where interim results provide immediate feedback while final results are accumulated for accuracy.</p>
<pre><code class="lang-javascript">      recognition.onresult = <span class="hljs-function">(<span class="hljs-params">event: any</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> finalTranscript = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">let</span> interimTranscript = <span class="hljs-string">""</span>;

        <span class="hljs-comment">// Process all results from the last processed index</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = event.resultIndex; i &lt; event.results.length; i++) {
          <span class="hljs-keyword">const</span> transcriptSegment = event.results[i][<span class="hljs-number">0</span>].transcript;
          <span class="hljs-keyword">if</span> (event.results[i].isFinal) {
            finalTranscript += transcriptSegment + <span class="hljs-string">" "</span>;
          } <span class="hljs-keyword">else</span> {
            interimTranscript += transcriptSegment;
          }
        }

        <span class="hljs-comment">// Update the current transcript</span>
        <span class="hljs-keyword">if</span> (finalTranscript) {
          currentTranscriptRef.current += finalTranscript;
        }

        <span class="hljs-comment">// Combine stored final transcript with current interim results</span>
        <span class="hljs-keyword">const</span> combinedTranscript = (currentTranscriptRef.current + interimTranscript).trim();

        <span class="hljs-comment">// Update the textarea</span>
        <span class="hljs-keyword">if</span> (combinedTranscript) {
          updateTextareaValue(combinedTranscript);
        }
      };
</code></pre>
<p>The lifecycle event handler ensures that the component responds appropriately to each phase of the speech recognition lifecycle events (<code>onstart</code>, <code>onend</code> and <code>onerror</code>):</p>
<pre><code class="lang-javascript">      recognition.onstart = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Speech recognition started"</span>);
        setIsRecording(<span class="hljs-literal">true</span>);
        currentTranscriptRef.current = <span class="hljs-string">""</span>; <span class="hljs-comment">// Reset transcript on start</span>
      };

      recognition.onend = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Speech recognition ended"</span>);
        setIsRecording(<span class="hljs-literal">false</span>);

        <span class="hljs-comment">// If it wasn't manually stopped and we're still supposed to be recording, restart</span>
        <span class="hljs-keyword">if</span> (!isManualStopRef.current &amp;&amp; isRecording) {
          <span class="hljs-keyword">try</span> {
            recognition.start();
          } <span class="hljs-keyword">catch</span> (error) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error restarting recognition:"</span>, error);
          }
        }

        isManualStopRef.current = <span class="hljs-literal">false</span>;
      };

      recognition.onerror = <span class="hljs-function">(<span class="hljs-params">event: any</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Speech recognition error:"</span>, event.error);
        setIsRecording(<span class="hljs-literal">false</span>);
        isManualStopRef.current = <span class="hljs-literal">false</span>;

        <span class="hljs-keyword">switch</span> (event.error) {
          <span class="hljs-keyword">case</span> <span class="hljs-string">"no-speech"</span>:
            <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"No speech detected"</span>);
            <span class="hljs-comment">// Don't show alert for no-speech, just log it</span>
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"not-allowed"</span>:
            alert(
              <span class="hljs-string">"Microphone access denied. Please allow microphone permissions."</span>,
            );
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"network"</span>:
            alert(<span class="hljs-string">"Network error occurred. Please check your connection."</span>);
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">case</span> <span class="hljs-string">"aborted"</span>:
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Speech recognition aborted"</span>);
            <span class="hljs-keyword">break</span>;
          <span class="hljs-keyword">default</span>:
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Speech recognition error:"</span>, event.error);
        }
      };

      recognitionRef.current = recognition;
      setIsRecognitionReady(<span class="hljs-literal">true</span>);
      } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"Web Speech API not supported in this browser."</span>);
      setIsRecognitionReady(<span class="hljs-literal">false</span>);
      }
</code></pre>
<h4 id="heading-starting-voice-input">Starting Voice Input</h4>
<p>When a user clicks the microphone button, the component initiates a multi-step process that involves requesting microphone permissions and providing clear error handling if users deny access.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> toggleRecording = <span class="hljs-keyword">async</span> (): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-keyword">void</span>&gt; =&gt; {
    <span class="hljs-keyword">if</span> (!recognitionRef.current) {
      alert(<span class="hljs-string">"Speech recognition not available"</span>);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">if</span> (isRecording) {
      <span class="hljs-comment">// Stop recording</span>
      isManualStopRef.current = <span class="hljs-literal">true</span>;
      recognitionRef.current.stop();
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Request microphone permission</span>
        <span class="hljs-keyword">await</span> navigator.mediaDevices.getUserMedia({ <span class="hljs-attr">audio</span>: <span class="hljs-literal">true</span> });

        <span class="hljs-comment">// Clear current text and reset transcript before starting</span>
        currentTranscriptRef.current = <span class="hljs-string">""</span>;
        updateTextareaValue(<span class="hljs-string">""</span>);

        <span class="hljs-comment">// Start recognition</span>
        recognitionRef.current.start();
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Microphone access error:"</span>, error);
        alert(
          <span class="hljs-string">"Unable to access microphone. Please check permissions and try again."</span>,
        );
      }
    }
  };
</code></pre>
<h4 id="heading-resetting-state-and-start-recognition">Resetting State and Start Recognition</h4>
<p>Before beginning speech recognition, the component resets its internal state. This reset ensures that each new voice input session starts with a clean slate, preventing interference from previous sessions.</p>
<pre><code class="lang-javascript">currentTranscriptRef.current = <span class="hljs-string">""</span>;
updateTextareaValue(<span class="hljs-string">""</span>);
recognitionRef.current.start();
</code></pre>
<h4 id="heading-real-time-speech-processing">Real-Time Speech Processing</h4>
<p>Two things happen simultaneously during this process:</p>
<ol>
<li><p><strong>Continuous Result Processing :</strong> As the user speaks, the component continuously processes incoming speech data through a sophisticated pipeline:</p>
<ul>
<li><p>Each speech segment is classified as either interim (temporary) or final (confirmed).</p>
</li>
<li><p>Final results are accumulated in the persistent transcript reference.</p>
</li>
<li><p>Interim results are combined with accumulated finals for immediate display.</p>
</li>
</ul>
</li>
<li><p><strong>Dynamic Textarea Updates:</strong> The component updates the <code>textarea</code> in real-time using a custom DOM manipulation approach:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> updateTextareaValue = <span class="hljs-function">(<span class="hljs-params">value: string</span>) =&gt;</span> {
   <span class="hljs-keyword">const</span> nativeInputValueSetter = <span class="hljs-built_in">Object</span>.getOwnPropertyDescriptor(
     <span class="hljs-built_in">window</span>.HTMLTextAreaElement.prototype,
     <span class="hljs-string">'value'</span>
   )?.set;

   <span class="hljs-keyword">if</span> (nativeInputValueSetter) {
     nativeInputValueSetter.call(textareaRef.current, value);
     <span class="hljs-keyword">const</span> inputEvent = <span class="hljs-keyword">new</span> Event(<span class="hljs-string">'input'</span>, { <span class="hljs-attr">bubbles</span>: <span class="hljs-literal">true</span> });
     textareaRef.current.dispatchEvent(inputEvent);
   }
 };
</code></pre>
<p> This step involves bypassing React's conventional controlled component behavior to provide immediate feedback, while still maintaining compatibility with React's event system.</p>
</li>
</ol>
<h4 id="heading-user-interface-feedback">User Interface Feedback</h4>
<p>To make voice interactions feel smoother for users, we’ll add some visual feedback features. These include:</p>
<ol>
<li><p><strong>Toggling between mic and stop icons</strong></p>
<p> We show a microphone icon when idle and a stop icon when recording is active. This provides a clear indication of the recording state.</p>
<pre><code class="lang-javascript"> &lt;button
   className={<span class="hljs-string">`voice-input-button <span class="hljs-subst">${isRecording ? <span class="hljs-string">'recording'</span> : <span class="hljs-string">'idle'</span>}</span>`</span>}
   title={isRecording ? <span class="hljs-string">"Stop recording"</span> : <span class="hljs-string">"Start voice input"</span>}
 &gt;
   {isRecording ? (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Square</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{20}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"voice-icon recording-icon"</span> /&gt;</span></span>
   ) : (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Mic</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{20}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"voice-icon idle-icon"</span> /&gt;</span></span>
   )}
 &lt;/button&gt;
</code></pre>
</li>
<li><p><strong>Recording notification banner</strong></p>
<p> A notification banner appears at the top of the screen to indicate that voice recording is in progress. This notification ensures users are aware when the microphone is active, addressing privacy and usability concerns.</p>
<pre><code class="lang-javascript"> {isRecording &amp;&amp; (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recording-notification show"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recording-icon"</span>&gt;</span>🎤<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
     Recording... Click stop when finished
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 )}
</code></pre>
</li>
</ol>
<h4 id="heading-message-integration-and-submission">Message Integration and Submission</h4>
<p>The transcribed text integrates seamlessly with the existing chat system through the shared <code>textarea</code> reference and context-provided submission handler:</p>
<pre><code class="lang-javascript">&lt;SendButton sendMessage={handleSubmit} /&gt;
</code></pre>
<p>This integration means that voice-generated messages follow the same submission pathway as typed messages, maintaining consistency with the chat system's behavior. After message submission, the component ensures proper cleanup of its internal state, preparing for the next voice input session.</p>
<h4 id="heading-passing-the-custommessageinput-component">Passing the CustomMessageInput component</h4>
<p>Having built our custom messaging input component, we’ll now pass it to the <code>Input</code> prop of the <code>MessageInput</code> component in our <code>App.tsx</code>:</p>
<pre><code class="lang-javascript">&lt;MessageInput Input={CustomMessageInput} /&gt;
</code></pre>
<h2 id="heading-complete-process-flow"><strong>Complete Process Flow</strong></h2>
<p>Here’s how the application works:</p>
<ol>
<li><p>After the component mounts, you add the AI to the chat by clicking the <strong>Add AI</strong> button.</p>
</li>
<li><p>Click the <strong>mic icon</strong> to start recording.</p>
</li>
<li><p>Your browser will ask for permission to use the microphone.</p>
</li>
<li><p>If you <strong>deny</strong> permission, recording won't begin.</p>
</li>
<li><p>If you <strong>allow</strong> permission, recording and transcription start simultaneously.</p>
</li>
<li><p>Click the <strong>stop (square) icon</strong> to end the recording.</p>
</li>
<li><p>Click the <strong>send button</strong> to submit your message.</p>
</li>
<li><p>The AI processes your input and generates a response.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you’ve learned how to build a powerful conversational chatbot using Stream Chat and React. The application supports both text and voice inputs.</p>
<p>If you want to create your own engaging chat experiences, you can explore Stream <a target="_blank" href="https://getstream.io/chat/">Chat</a> and <a target="_blank" href="https://getstream.io/video/">Video</a> features to take your projects to the next level.</p>
<p>Get the full source code for this project <a target="_blank" href="https://github.com/TimothyOlanrewaju/My-Chat-Application">here</a>. If you enjoyed reading this article, connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750">LinkedIn</a> or follow me on <a target="_blank" href="https://x.com/SmoothTee_DC">X</a> for more programming-related posts and articles.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Dynamic Wardrobe App with React Drag and Drop ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever found yourself stuck deciding what color outfit to wear? Maybe you’re mixing and matching different tops and bottoms, unsure if the colors go together. It’s a common dilemma – so common that many of us turn to friends or family for a se... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-dynamic-wardrobe-app-with-react-drag-and-drop/</link>
                <guid isPermaLink="false">6818d1793c6be4514080aea9</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 05 May 2025 14:55:53 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746456835547/563ca5bd-27b0-421e-a0f3-a13f97388449.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever found yourself stuck deciding what color outfit to wear? Maybe you’re mixing and matching different tops and bottoms, unsure if the colors go together. It’s a common dilemma – so common that many of us turn to friends or family for a second opinion before stepping out for a meeting or a hangout.</p>
<p>But what if you’re alone and need to make that choice quickly? Imagine having an app where you can drag and drop different clothing colors on your screen, instantly visualizing your outfit. If it looks good, that’s all the validation you need – no more second-guessing your look.</p>
<p>In this tutorial, we’ll build a dynamic wardrobe app using React. You’ll learn to structure components, handle drag-and-drop interactions, and craft a smooth user experience. Let’s get straight into it!</p>
<h2 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-steps-to-create-a-dynamic-wardrobe-using-react">Steps to Create a Dynamic Wardrobe using React</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-setting-up-your-project">Step 1: Setting Up Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-setting-up-states">Step 2: Setting Up States</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-defining-color-options">Step 3: Defining Color Options</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-implementing-drag-and-drop-functionality">Step 4: Implementing Drag and Drop Functionality</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-building-the-user-interface">Step 5: Building the User Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-putting-it-all-together">Step 6: Putting It All Together</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before we start coding, make sure you have:</p>
<ul>
<li><p>Basic knowledge of React.</p>
</li>
<li><p>A code editor of your choice.</p>
</li>
</ul>
<h2 id="heading-steps-to-create-a-dynamic-wardrobe-using-react">Steps to Create a Dynamic Wardrobe using React</h2>
<p>We're going to go through how to build this project step by step, so it's easy to follow along. By the end, you'll understand exactly how drag and drop functionality in React works.</p>
<h3 id="heading-step-1-setting-up-your-project"><strong>Step 1: Setting Up Your Project</strong></h3>
<p>First and foremost, you need to set up React and Tailwind CSS using Vite in a project. If you don't know how to do that, check out this <a target="_blank" href="https://www.freecodecamp.org/news/how-to-install-tailwindcss-in-react/">article</a> and follow the steps. When you’re done, come back here, and let’s continue building.</p>
<p>If you already have a React project with Tailwind CSS you want to use, that’s great too.</p>
<h3 id="heading-step-2-setting-up-states"><strong>Step 2: Setting Up States</strong></h3>
<p>We'll start by setting up our states. If you have no idea what states are you can read my article on states <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/">here</a>. In this simple project, we’ll have only two states: one for the selected top color (<code>selectedTop</code>) and the other for the selected bottom color (<code>selectedBottom</code>). We’ll be setting the initial value of both states to <strong>white</strong> (with hex code of #ffffff), as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [selectedTop, setSelectedTop] = useState(<span class="hljs-string">"#ffffff"</span>);

<span class="hljs-keyword">const</span> [selectedBottom, setSelectedBottom] = useState(<span class="hljs-string">"#ffffff"</span>);
</code></pre>
<h3 id="heading-step-3-defining-color-options"><strong>Step 3: Defining Color Options</strong></h3>
<p>Next, we define an array of color options for the outfits:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> colorOptions = [

<span class="hljs-string">"#ff0000"</span>, <span class="hljs-comment">// Red</span>

<span class="hljs-string">"#0000ff"</span>, <span class="hljs-comment">// Blue</span>

<span class="hljs-string">"#ffff00"</span>, <span class="hljs-comment">// Yellow</span>

<span class="hljs-string">"#00ff00"</span>, <span class="hljs-comment">// Green</span>

<span class="hljs-string">"#ff00ff"</span>, <span class="hljs-comment">// Pink</span>

<span class="hljs-string">"#808080"</span>, <span class="hljs-comment">// Gray</span>

<span class="hljs-string">"#000000"</span>, <span class="hljs-comment">// Black</span>

<span class="hljs-string">"#ffffff"</span>, <span class="hljs-comment">// White</span>

];
</code></pre>
<p>The <code>colorOptions</code> array provides a vibrant palette of colors that users can drag onto clothing items.</p>
<h3 id="heading-step-4-implementing-drag-and-drop-functionality"><strong>Step 4: Implementing Drag and Drop Functionality</strong></h3>
<p>Now, let's create the drag and drop functionality, which is the core aspect of this project. We’ll need event handler functions to handle certain events when they are triggered by specific user interaction or browser events – in this case, dragging and dropping.</p>
<p>Here are the event handlers we need to implement the drag and drop functionality:</p>
<ol>
<li><code>handleDragStart</code></li>
</ol>
<p>This function is triggered when the user starts dragging a color block from the color palette (typically triggered via <code>onDragStart</code> in JSX).</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleDragStart = <span class="hljs-function">(<span class="hljs-params">e, color</span>) =&gt;</span> {

e.dataTransfer.setData(<span class="hljs-string">"color"</span>, color);

};
</code></pre>
<p>Breaking it down:</p>
<ul>
<li><p><code>const handleDragStart = (e, color) =&gt; { ... }</code>: This function accepts two parameters – the <strong>drag event object (e)</strong> and <strong>color</strong>, a custom value representing the color associated with the color block being dragged.</p>
</li>
<li><p><code>e.dataTransfer.setData("color", color)</code>:</p>
<ul>
<li><p><code>dataTransfer</code> is a property of the drag event that holds data being dragged.</p>
</li>
<li><p><code>.setData("color", color)</code> stores the value of color under the key "color".</p>
</li>
</ul>
</li>
</ul>
<ol start="2">
<li><code>handleDropOnTop</code></li>
</ol>
<p>This function is triggered when the color block is dropped onto the "<strong>top</strong>" section of your outfit interface.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleDropOnTop = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {

e.preventDefault();

<span class="hljs-keyword">const</span> color = e.dataTransfer.getData(<span class="hljs-string">"color"</span>);

setSelectedTop(color);

};
</code></pre>
<p>Breaking it down:</p>
<ul>
<li><p><code>const handleDropOnTop = (e) =&gt; { … }</code>: This function takes a single argument <strong>e</strong>, which is the event object representing the drop action.</p>
</li>
<li><p><code>e.preventDefault()</code>: By default, the browser won’t allow dropping an item unless you explicitly prevent the default behavior. This ensures the drop target can accept the dragged item.</p>
</li>
<li><p><code>const color = e.daaTransfer.getData(“color”)</code>: retrieves the data previously set during the drag operation using <code>setData(“color”, color)</code> in <code>handleDragStart</code> .</p>
</li>
<li><p><code>setSelectedTop(color)</code>: The <code>color</code> data will be used to update the <code>selectedTop</code> state that tracks the currently selected top clothing color. This will typically cause the UI to re-render, showing the dropped color on the “top” section of the outfit.</p>
</li>
</ul>
<ol start="3">
<li><code>handleDropOnBottom</code></li>
</ol>
<p>This function is triggered when the color block is dropped onto the "<strong>bottom</strong>" section of your outfit interface.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleDropOnBottom = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {

e.preventDefault();

<span class="hljs-keyword">const</span> color = e.dataTransfer.getData(<span class="hljs-string">"color"</span>);

setSelectedBottom(color);

};
</code></pre>
<p>Breaking it down:</p>
<ul>
<li><p><code>const handleDropOnBottom = (e) =&gt; { ... }</code>: This function takes a single argument <strong>e</strong>, which is the event object representing the drop action.</p>
</li>
<li><p><code>e.preventDefault()</code>: By default, the browser won’t allow dropping an item unless you explicitly prevent the default behavior. This ensures the drop target can accept the dragged item.</p>
</li>
<li><p><code>const color = e.dataTransfer.getData("color")</code>: Retrieves the data previously set during the drag operation using <code>setData("color", color)</code> in <code>handleDragStart</code>.</p>
</li>
<li><p><code>setSelectedBottom(color)</code>: The <code>color</code> data will be used to update the <code>selectedBottom</code> state that tracks the currently selected top clothing color. This will typically cause the UI to re-render, showing the dropped color on the “bottom” section of the outfit.</p>
</li>
</ul>
<ol start="4">
<li><code>allowDrop</code></li>
</ol>
<p>This event handler function enables a drop target by preventing the browser's default behavior, which otherwise disallows dropping elements.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> allowDrop = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {

e.preventDefault();

};
</code></pre>
<h3 id="heading-step-5-building-the-user-interface"><strong>Step 5: Building the User Interface</strong></h3>
<p>Having finished the functional part of our wardrobe project, we want to build out the visual part that users can see and interact with.</p>
<p>The UI will consist of two parts: a color palette on the left and an outfit preview on the right. The color palette section will include 30 color blocks while the outfit preview section will include a top and bottom, onto which selected colors can be dragged and applied to see how they look together.</p>
<p>This is a visual representation of the UI we’re building out:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746193425525/449e4294-8917-470e-ad06-cf54d1809296.png" alt="449e4294-8917-470e-ad06-cf54d1809296" class="image--center mx-auto" width="1903" height="828" loading="lazy"></p>
<h4 id="heading-creating-the-color-palette-section">Creating the Color Palette Section</h4>
<p>To display all the colors provided in our <code>colorOptions</code> array, we need to first map through the array consisting of color values and render a <code>&lt;div&gt;</code> for each color.</p>
<p>Each <code>&lt;div&gt;</code>:</p>
<ul>
<li><p>Acts as a <strong>draggable color block</strong> with fixed width and height.</p>
</li>
<li><p>Has a semi-circular appearance using Tailwind CSS classes and inline styling to apply the specific background color.</p>
</li>
<li><p>Triggers the <code>handleDragStart</code> function when dragging begins, passing the event and the selected color.</p>
</li>
<li><p>Has a unique key for React's rendering optimization.</p>
</li>
<li><p>If the color is white (<code>#ffffff</code>), it conditionally displays the text "<strong>White</strong>" in light gray for visibility.</p>
</li>
</ul>
<p>This setup allows users to visually identify and drag different color options to the top or bottom of an outfit on the UI.</p>
<pre><code class="lang-javascript"><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 items-center p-6 bg-gray-100 rounded-lg min-h-screen"</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 font-extrabold mb-8 text-indigo-700"</span>&gt;</span>
      Dynamic Wardrobe
    <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col md:flex-row w-full gap-8"</span>&gt;</span>
      {/* Color palette section */}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full md:w-1/3 bg-white p-6 rounded-lg shadow-md"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl font-semibold mb-4 text-center"</span>&gt;</span>
          Color Palette
        <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-4 text-sm text-gray-600"</span>&gt;</span>
          Drag colors to the outfit pieces
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-5 gap-2"</span>&gt;</span>
          {colorOptions.map((color) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
              <span class="hljs-attr">key</span>=<span class="hljs-string">{color}</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12 h-12 rounded-md shadow-sm cursor-move flex items-center justify-center"</span>
              <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> <span class="hljs-attr">color</span>, <span class="hljs-attr">border:</span> "<span class="hljs-attr">1px</span> <span class="hljs-attr">solid</span> #<span class="hljs-attr">ddd</span>" }}
              <span class="hljs-attr">draggable</span>=<span class="hljs-string">"true"</span>
              <span class="hljs-attr">onDragStart</span>=<span class="hljs-string">{(e)</span> =&gt;</span> handleDragStart(e, color)}
            &gt;
              {color === "#ffffff" &amp;&amp; (
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xs text-gray-400"</span>&gt;</span>White<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>&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>
<h4 id="heading-creating-the-outfit-preview">Creating the Outfit Preview</h4>
<p>Finally, let's implement the outfit preview section, which is the fun part. There are two parts to the outfit display: the top and the bottom section. Let’s look at them one after the other:</p>
<h4 id="heading-top-section">Top Section</h4>
<p>This section acts as a <strong>drop target for the top clothing color</strong>. It consists of a div with an SVG that allows for color filling.</p>
<pre><code class="lang-javascript">&lt;div
  className=<span class="hljs-string">"w-full flex items-center justify-center"</span>
  onDrop={handleDropOnTop}
  onDragOver={allowDrop}
&gt;
  {<span class="hljs-comment">/* T-shirt */</span>}
  &lt;svg viewBox=<span class="hljs-string">"0 0 24 24"</span> width=<span class="hljs-string">"180"</span> height=<span class="hljs-string">"140"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">path</span>
      <span class="hljs-attr">d</span>=<span class="hljs-string">"M16 2H8L6 6v3h2v13h8V9h2V6l-2-4z"</span>
      <span class="hljs-attr">fill</span>=<span class="hljs-string">{selectedTop}</span>
      <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#333"</span>
      <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"0.2"</span>
    /&gt;</span></span>
  &lt;/svg&gt;
&lt;/div&gt;;
</code></pre>
<p>In this section:</p>
<ul>
<li><p><code>onDrop={handleDropOnTop}</code>: Sets the top outfit color, when a color is dropped at the top div.</p>
</li>
<li><p><code>allowDrop</code> is called via <code>onDragOver</code> to enable dropping.</p>
</li>
<li><p>The T-shirt SVG is drawn and its fill color is controlled by <code>selectedTop</code>, which updates when a new color is dropped.</p>
</li>
</ul>
<h4 id="heading-bottom-section">Bottom Section</h4>
<p>This section acts as a <strong>drop target for the bottom clothing color</strong>. It consists of a div with an SVG that allows for color filling.</p>
<pre><code class="lang-javascript">&lt;div
  className=<span class="hljs-string">"w-full flex items-center justify-center -mt-8"</span>
  onDrop={handleDropOnBottom}
  onDragOver={allowDrop}
&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 200 200"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"120"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"140"</span>&gt;</span>
    {/* Pants */}
    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
      <span class="hljs-attr">d</span>=<span class="hljs-string">"M60,20 L140,20 L150,180 L110,180 L100,100 L90,180 L50,180 L60,20 Z"</span>
      <span class="hljs-attr">fill</span>=<span class="hljs-string">{selectedBottom}</span>
      <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#333"</span>
      <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"2"</span>
    /&gt;</span>
    {/* Waistband */}
    <span class="hljs-tag">&lt;<span class="hljs-name">rect</span> <span class="hljs-attr">x</span>=<span class="hljs-string">"60"</span> <span class="hljs-attr">y</span>=<span class="hljs-string">"18"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"80"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"5"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"#444"</span> /&gt;</span>
    {/* Center seam */}
    <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M100,20 L100,100"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#000"</span> <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"1"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
&lt;/div&gt;;
</code></pre>
<p>In this section:</p>
<ul>
<li><p><code>onDrop={handleDropOnBottom}</code>: Sets the bottom outfit color, when a color is dropped at the bottom div.</p>
</li>
<li><p><code>allowDrop</code> is called via <code>onDragOver</code> to enable dropping.</p>
</li>
<li><p>The pant SVG is drawn and its fill color is controlled by <code>selectedBottom</code>, which updates when a new color is dropped.</p>
</li>
<li><p>Extra details like a waistband (rect) and a seam (path) add realism.</p>
</li>
</ul>
<p>That completes the UI section of our project.</p>
<h3 id="heading-step-6-putting-it-all-together">Step 6: Putting It All Together</h3>
<p>Now that you’ve learned about the integral aspects, here is the full code that will give you the entire look and functionality:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</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-comment">// State for selected colors</span>
  <span class="hljs-keyword">const</span> [selectedTop, setSelectedTop] = useState(<span class="hljs-string">"#ffffff"</span>);
  <span class="hljs-keyword">const</span> [selectedBottom, setSelectedBottom] = useState(<span class="hljs-string">"#ffffff"</span>);

  <span class="hljs-comment">// Color options for clothing</span>
  <span class="hljs-keyword">const</span> colorOptions = [
    <span class="hljs-string">"#ff0000"</span>, <span class="hljs-comment">// Red</span>
    <span class="hljs-string">"#0000ff"</span>, <span class="hljs-comment">// Blue</span>
    <span class="hljs-string">"#ffff00"</span>, <span class="hljs-comment">// Yellow</span>
    <span class="hljs-string">"#00ff00"</span>, <span class="hljs-comment">// Green</span>
    <span class="hljs-string">"#ff00ff"</span>, <span class="hljs-comment">// Pink</span>
    <span class="hljs-string">"#808080"</span>, <span class="hljs-comment">// Gray</span>
    <span class="hljs-string">"#000000"</span>, <span class="hljs-comment">// Black</span>
    <span class="hljs-string">"#ffffff"</span>, <span class="hljs-comment">// White</span>
    <span class="hljs-string">"#ffa500"</span>, <span class="hljs-comment">// Orange</span>
    <span class="hljs-string">"#800080"</span>, <span class="hljs-comment">// Purple</span>
    <span class="hljs-string">"#8B0000"</span>, <span class="hljs-comment">// Dark Red</span>
    <span class="hljs-string">"#006400"</span>, <span class="hljs-comment">// Dark Green</span>
    <span class="hljs-string">"#00008B"</span>, <span class="hljs-comment">// Dark Blue</span>
    <span class="hljs-string">"#4B0082"</span>, <span class="hljs-comment">// Indigo</span>
    <span class="hljs-string">"#228B22"</span>, <span class="hljs-comment">// Forest Green</span>
    <span class="hljs-string">"#20B2AA"</span>, <span class="hljs-comment">// Light Sea Green</span>
    <span class="hljs-string">"#87CEEB"</span>, <span class="hljs-comment">// Sky Blue</span>
    <span class="hljs-string">"#4682B4"</span>, <span class="hljs-comment">// Steel Blue</span>
    <span class="hljs-string">"#9932CC"</span>, <span class="hljs-comment">// Dark Orchid</span>
    <span class="hljs-string">"#FF1493"</span>, <span class="hljs-comment">// Deep Pink</span>
    <span class="hljs-string">"#FF4500"</span>, <span class="hljs-comment">// Orange Red</span>
    <span class="hljs-string">"#FFD700"</span>, <span class="hljs-comment">// Gold</span>
    <span class="hljs-string">"#F0E68C"</span>, <span class="hljs-comment">// Khaki</span>
    <span class="hljs-string">"#F5DEB3"</span>, <span class="hljs-comment">// Wheat</span>
    <span class="hljs-string">"#D2B48C"</span>, <span class="hljs-comment">// Tan</span>
    <span class="hljs-string">"#A0522D"</span>, <span class="hljs-comment">// Sienna</span>
    <span class="hljs-string">"#8B4513"</span>, <span class="hljs-comment">// Saddle Brown</span>
    <span class="hljs-string">"#BC8F8F"</span>, <span class="hljs-comment">// Rosy Brown</span>
    <span class="hljs-string">"#708090"</span>, <span class="hljs-comment">// Slate Gray</span>
    <span class="hljs-string">"#2F4F4F"</span>, <span class="hljs-comment">// Dark Slate Gray</span>
  ];

  <span class="hljs-comment">// Drag and drop handlers</span>
  <span class="hljs-keyword">const</span> handleDragStart = <span class="hljs-function">(<span class="hljs-params">e, color</span>) =&gt;</span> {
    e.dataTransfer.setData(<span class="hljs-string">"color"</span>, color);
  };

  <span class="hljs-keyword">const</span> handleDropOnTop = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();
    <span class="hljs-keyword">const</span> color = e.dataTransfer.getData(<span class="hljs-string">"color"</span>);
    setSelectedTop(color);
  };

  <span class="hljs-keyword">const</span> handleDropOnBottom = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();
    <span class="hljs-keyword">const</span> color = e.dataTransfer.getData(<span class="hljs-string">"color"</span>);
    setSelectedBottom(color);
  };

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

  <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 items-center p-6 bg-gray-100 rounded-lg min-h-screen"</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 font-extrabold mb-8 text-indigo-700"</span>&gt;</span>
        Dynamic Wardrobe
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col md:flex-row w-full gap-8"</span>&gt;</span>
        {/* Color palette section */}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full md:w-1/3 bg-white p-6 rounded-lg shadow-md"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl font-semibold mb-4 text-center"</span>&gt;</span>
            Color Palette
          <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-4 text-sm text-gray-600"</span>&gt;</span>
            Drag colors to the outfit pieces
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-5 gap-2"</span>&gt;</span>
            {colorOptions.map((color) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
                <span class="hljs-attr">key</span>=<span class="hljs-string">{color}</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12 h-12 rounded-md shadow-sm cursor-move flex items-center justify-center"</span>
                <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> <span class="hljs-attr">color</span>, <span class="hljs-attr">border:</span> "<span class="hljs-attr">1px</span> <span class="hljs-attr">solid</span> #<span class="hljs-attr">ddd</span>" }}
                <span class="hljs-attr">draggable</span>=<span class="hljs-string">"true"</span>
                <span class="hljs-attr">onDragStart</span>=<span class="hljs-string">{(e)</span> =&gt;</span> handleDragStart(e, color)}
              &gt;
                {color === "#ffffff" &amp;&amp; (
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xs text-gray-400"</span>&gt;</span>White<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>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        {/* Outfit visualization section */}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full md:w-2/3 bg-white p-6 rounded-lg shadow-md"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl font-semibold mb-4 text-center"</span>&gt;</span>
            Outfit Preview
          <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">"flex flex-col items-center"</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 w-64 h-64"</span>&gt;</span>
              {/* Outfit container - better positioning */}
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative w-full h-full flex flex-col items-center justify-center"</span>&gt;</span>
                {/* Top Section - accepts drag and drop */}
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full flex items-center justify-center"</span>
                  <span class="hljs-attr">onDrop</span>=<span class="hljs-string">{handleDropOnTop}</span>
                  <span class="hljs-attr">onDragOver</span>=<span class="hljs-string">{allowDrop}</span>
                &gt;</span>
                  {/* T-shirt */}
                  <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"180"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"140"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                      <span class="hljs-attr">d</span>=<span class="hljs-string">"M16 2H8L6 6v3h2v13h8V9h2V6l-2-4z"</span>
                      <span class="hljs-attr">fill</span>=<span class="hljs-string">{selectedTop}</span>
                      <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#333"</span>
                      <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"0.2"</span>
                    /&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">svg</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">"w-full flex items-center justify-center -mt-8"</span>
                  <span class="hljs-attr">onDrop</span>=<span class="hljs-string">{handleDropOnBottom}</span>
                  <span class="hljs-attr">onDragOver</span>=<span class="hljs-string">{allowDrop}</span>
                &gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 200 200"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"120"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"140"</span>&gt;</span>
                    {/* Pants */}
                    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                      <span class="hljs-attr">d</span>=<span class="hljs-string">"M60,20 L140,20 L150,180 L110,180 L100,100 L90,180 L50,180 L60,20 Z"</span>
                      <span class="hljs-attr">fill</span>=<span class="hljs-string">{selectedBottom}</span>
                      <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#333"</span>
                      <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"2"</span>
                    /&gt;</span>
                    {/* Waistband */}
                    <span class="hljs-tag">&lt;<span class="hljs-name">rect</span> <span class="hljs-attr">x</span>=<span class="hljs-string">"60"</span> <span class="hljs-attr">y</span>=<span class="hljs-string">"18"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"80"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"5"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"#444"</span> /&gt;</span>
                    {/* Center seam */}
                    <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M100,20 L100,100"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"#000"</span> <span class="hljs-attr">strokeWidth</span>=<span class="hljs-string">"1"</span> /&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here’s our dynamic wardrobe in full flow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746197218776/e840ecd6-665f-41b4-a590-02e91302cf26.gif" alt="e840ecd6-665f-41b4-a590-02e91302cf26" class="image--center mx-auto" width="1000" height="500" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This dynamic wardrobe project demonstrates the power of React's drag and drop API combined with state management. Not only is it a fun project to build, but it also taught you important concepts like managing state in React components, implementing drag and drop functionality, creating responsive layouts with Tailwind CSS and using SVG for interactive visuals.</p>
<p>If you enjoyed reading this tutorial, you could <a target="_blank" href="https://buymeacoffee.com/timothyolanrewaju">Buy Me a Coffee</a>. You can also connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750">LinkedIn</a> for more programming-related posts and articles.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Dependent Dropdowns in React ]]>
                </title>
                <description>
                    <![CDATA[ In many web applications, we often encounter forms where selecting an option in one dropdown unlocks a new set of options in another. These interconnected dropdowns, commonly known as dependent or cascading dropdowns, play a crucial role in creating ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-dependent-dropdowns-in-react/</link>
                <guid isPermaLink="false">679b92469bbf0da70b05703a</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 30 Jan 2025 14:52:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738246583123/caa07859-2ce8-44b1-9fd2-44b414babe52.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In many web applications, we often encounter forms where selecting an option in one dropdown unlocks a new set of options in another. These interconnected dropdowns, commonly known as dependent or cascading dropdowns, play a crucial role in creating a seamless and intuitive form-filling experience.</p>
<p>Whether it's selecting a country to reveal corresponding states or choosing a product category to display specific items, these dropdowns simplify complex choices for everyone. For developers, implementing dependent dropdowns is a practical challenge that combines logic, usability, and dynamic data handling.</p>
<p>In this tutorial, you’ll learn how to implement this type of dropdown in your React application.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-dependent-dropdown">What is a Dependent Dropdown?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-does-a-dependent-dropdown-work">How Does a Dependent Dropdown Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-steps-to-create-dependent-dropdowns-in-react">Steps to Create Dependent Dropdowns in React</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-set-up-your-react-project">Step 1: Set up Your React Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-structure-the-component">Step 2: Structure the Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-use-the-component">Step 3: Use the Component</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-handling-dynamic-data-api-requests">Handling Dynamic Data (API Requests)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-dependent-dropdown"><strong>What is a Dependent Dropdown?</strong></h2>
<p>A dependent dropdown is a UI element in which the available options in one dropdown are determined by the selection made in another dropdown. For example, consider a scenario where you have two dropdowns:</p>
<ol>
<li><p>Country Dropdown: The user selects a country.</p>
</li>
<li><p>City Dropdown: Based on the selected country, the list of available cities in the second dropdown will be filtered accordingly.</p>
</li>
</ol>
<p>This kind of interaction is crucial for forms that require complex, context-sensitive data inputs.</p>
<h2 id="heading-how-does-a-dependent-dropdown-work"><strong>How Does a Dependent Dropdown Work?</strong></h2>
<p>Dependent dropdowns work by having the second dropdown’s options dynamically updated based on the value selected in the first dropdown. This dynamic change is typically achieved by:</p>
<ol>
<li><p><strong>Listening to user input:</strong> When the user selects an option in the first dropdown, an event (usually onChange) triggers a function to update the state.</p>
</li>
<li><p><strong>Fetching new data:</strong> This updated state can be used to either filter the existing data or make an API call to fetch the new list of options.</p>
</li>
<li><p><strong>Rendering new data:</strong> The second dropdown is then updated with the new options, providing the user with relevant choices.</p>
</li>
</ol>
<h2 id="heading-steps-to-create-dependent-dropdowns-in-react"><strong>Steps to Create Dependent Dropdowns in React</strong></h2>
<h3 id="heading-step-1-set-up-your-react-project"><strong>Step 1: Set up Your React Project</strong></h3>
<p>If you’re new to React and wish to follow along, <a target="_blank" href="https://vite.dev/guide/">check out the Vite docs</a> and follow the steps to create your React project. When you’re done, come back here and let’s continue building.</p>
<p>If you already have a React project you want to use, that’s great too.</p>
<h3 id="heading-step-2-structure-the-component"><strong>Step 2: Structure the Component</strong></h3>
<p>For simplicity, let’s assume we are building a two-level dependent dropdown where the first dropdown lets you choose a country, and the second dropdown displays cities based on the selected country.</p>
<p>Also, in the country dropdown, we’ll have another option for entering a country name that is not included in the countries options. The user can then proceed to enter their country in a text input.</p>
<p>First, create a new file named <code>DependentDropdown.js</code> or <code>DependentDropdown.jsx</code>. Inside this file, define a functional component called <code>DependentDropdown</code>.</p>
<p>Now we’ll be going through the following steps to build our dependent dropdown:</p>
<p><strong>Declare Variables for Storing Data</strong></p>
<p>We need to create static data for the values of our countries and cities:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// Static country data</span>
  <span class="hljs-keyword">const</span> countries = [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'USA'</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Canada'</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Other'</span> },
  ];

  <span class="hljs-comment">// Static city data corresponding to countries</span>
  <span class="hljs-keyword">const</span> cities = {
    <span class="hljs-attr">USA</span>: [<span class="hljs-string">'New York'</span>, <span class="hljs-string">'Los Angeles'</span>, <span class="hljs-string">'Chicago'</span>],
    <span class="hljs-attr">Canada</span>: [<span class="hljs-string">'Toronto'</span>, <span class="hljs-string">'Vancouver'</span>, <span class="hljs-string">'Montreal'</span>],
  };
</code></pre>
<ul>
<li><p><code>countries</code> is an array of objects. Each object having properties of <code>id</code> and <code>name</code>.</p>
</li>
<li><p><code>cities</code> is an object with country names as keys and the values as array of cities.</p>
</li>
</ul>
<p><strong>Declare State Variables</strong></p>
<p>For each selection of either country or cities, we want to be able to keep track of the values selected. We also want to be able to populate the cities option after a country selection has been made. To do that, we need to declare some states.</p>
<p>If the concept of state is new to you, you can read my article on state <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/">here</a>.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [selectedCountry, setSelectedCountry] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [availableCities, setAvailableCities] = useState([]);
  <span class="hljs-keyword">const</span> [selectedCity, setSelectedCity] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [otherCountry, setOtherCountry] = useState(<span class="hljs-string">''</span>);
</code></pre>
<ul>
<li><p>The <code>selectedCountry</code> state is declared and its initial value is set to an empty string.</p>
</li>
<li><p>The <code>availableCities</code> state is declared and its initial value is set to an empty array.</p>
</li>
<li><p>The <code>selectedCity</code> state is declared and its initial value is set to an empty string.</p>
</li>
<li><p>The <code>otherCountry</code> state is declared and its initial value is set to an empty string.</p>
</li>
</ul>
<p><strong>Handling Events</strong></p>
<p>In the process of making a selection in the dropdown, we want some actions to be performed. Event handlers enable us to do that in the case of an event, which in this case is the <code>onChange</code> event.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleCountryChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> country = e.target.value;
    setSelectedCountry(country);
    setAvailableCities(cities[country] || []);
    setSelectedCity(<span class="hljs-string">''</span>); 
     <span class="hljs-keyword">if</span> (country !== <span class="hljs-string">'Other'</span>) {
      setOtherCountry(<span class="hljs-string">''</span>);
    }
  };
</code></pre>
<p>Here’s what’s going on in the <code>handleCountryChange</code> function:</p>
<ul>
<li><p>Grabs the value of the selected option in the dropdown (the country that was selected).</p>
</li>
<li><p>The <code>setSelectedCountry</code> updates the state variable (selectedCountry) with the newly selected country.</p>
</li>
<li><p><code>cities[country]</code> looks up the list of cities for the selected country from the <code>cities</code> object.</p>
<ul>
<li><p>If <code>cities[country]</code> is found, it sets that list of cities as the available cities.</p>
</li>
<li><p>If no cities are found for the selected country (<code>cities[country]</code> is undefined), the <code>|| []</code> ensures that an empty array (<code>[]</code>) is used as a fallback, preventing errors when trying to display the cities.</p>
</li>
</ul>
</li>
<li><p>When the user changes the country selection, the <code>setSelectedCity</code> function resets the <code>selectedCity</code> to an empty string.</p>
</li>
<li><p>If the country selected is not ‘Other’, the <code>otherCountry</code> state is reset to an empty string. This ensures that if the user had previously typed something into the "Other" input, that text is cleared once they select a different country (for example, "USA" or "Canada").</p>
</li>
</ul>
<p>For the ‘Other’ country selection, we just need to keep track of the value entered into the input. The <code>setOtherCountry</code> function updates the value entered. And this is how it is done:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleOtherCountryChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setOtherCountry(e.target.value);
  };
</code></pre>
<p>For the cities change, we don’t need to do much because the selected country determines which cities are displayed. All we need to do is to update the <code>selectedCity</code> to the value of the selected option in the dropdown, which is the city that is selected.</p>
<p>In React, the updater function does the updating of state variables, so the <code>setSelectedCity</code> handles this in this case.</p>
<p>The <code>handleCityChange</code> function will be:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleCityChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setSelectedCity(e.target.value);
  };
</code></pre>
<p><strong>Returning JSX</strong></p>
<p>The <code>DependentDropdown</code> component renders three main elements: the Country dropdown, the City dropdown, and the Country text input.</p>
<p>A dropdown in HTML is a combination of the <code>&lt;select&gt;</code> and <code>&lt;option&gt;</code> elements. To keep track of the value of elements, we’ll attach state variables to them so we can control them. Doing this is called 'Controlling Elements', while the elements themselves are referred to as 'Controlled Elements' in React.</p>
<p>To control the country <code>&lt;select&gt;</code> element, we’ll give it a <code>value</code> attribute of <code>selectedCountry</code> and also attach the <code>handleCountryChange</code> function to it.</p>
<pre><code class="lang-javascript">     &lt;label htmlFor=<span class="hljs-string">"country"</span> className=<span class="hljs-string">'font-bold'</span>&gt;Select Country: &lt;/label&gt;
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"country"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedCountry}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleCountryChange}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Select a country<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        {countries.map((country) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{country.id}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{country.name}</span>&gt;</span>
            {country.name}
          <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>
</code></pre>
<p>Also,</p>
<ul>
<li><p>Inside the <code>&lt;option&gt;</code>, we map over the <code>countries</code> array and dynamically create an <code>&lt;option&gt;</code> for each country object in the array.</p>
</li>
<li><p>Each country’s <code>name</code> is displayed as the option’s text.</p>
</li>
<li><p>Each option’s <code>key</code> is set to the country’s <code>id</code> and <code>value</code> is set to the country’s <code>name</code>.</p>
</li>
<li><p>The <code>key</code> helps React manage the list efficiently when re-rendering.</p>
</li>
</ul>
<p>The Cities dropdown is conditionally rendered based on the selected country. If the 'Other' country option is chosen, a text input field is displayed for the user to specify the country. Otherwise, if a valid country is selected, a Cities dropdown with relevant options is shown.</p>
<pre><code class="lang-javascript">{selectedCountry === <span class="hljs-string">'Other'</span> ? (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"other-country"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-bold'</span>&gt;</span>Please specify the country: <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">id</span>=<span class="hljs-string">"other-country"</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{otherCountry}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleOtherCountryChange}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter country name"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      ) : (
        selectedCountry &amp;&amp; (
          <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"city"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-bold'</span>&gt;</span>Select City: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"city"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedCity}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleCityChange}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Select a city<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
              {availableCities.map((city, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{city}</span>&gt;</span>
                  {city}
                <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;/&gt;</span></span>
        )
      )
}
</code></pre>
<p>Additionally:</p>
<ul>
<li><p>We check if <code>selectedCountry</code> is the ‘Other’ option and display a text input.</p>
</li>
<li><p>The text input has a <code>otherCountry</code> state and the <code>handleOtherCountryChange</code> handler function attached to it.</p>
</li>
<li><p>We control the city <code>&lt;select&gt;</code> element using the <code>value</code> attribute, setting it to the state variable of <code>selectedCity</code>. The event handler, <code>handleCityChange</code>, is also attached to handle <code>onChange</code> events.</p>
</li>
<li><p>We map over the <code>availableCities</code> array and dynamically create an <code>&lt;option&gt;</code> for each city in the array.</p>
</li>
<li><p>Each option’s <code>key</code> is set to an <code>index</code> and <code>value</code> is set to the <code>city</code>.</p>
</li>
<li><p>Each city is displayed as the option’s text.</p>
</li>
</ul>
<p>That’s all we have to do to have a functional dependent dropdown using our static data.</p>
<p>Here is all the code put together:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> DependentDropdown = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Static country data</span>
  <span class="hljs-keyword">const</span> countries = [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'USA'</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Canada'</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Other'</span> },
  ];

  <span class="hljs-comment">// Static city data corresponding to countries</span>
  <span class="hljs-keyword">const</span> cities = {
    <span class="hljs-attr">USA</span>: [<span class="hljs-string">'New York'</span>, <span class="hljs-string">'Los Angeles'</span>, <span class="hljs-string">'Chicago'</span>],
    <span class="hljs-attr">Canada</span>: [<span class="hljs-string">'Toronto'</span>, <span class="hljs-string">'Vancouver'</span>, <span class="hljs-string">'Montreal'</span>],
  };

  <span class="hljs-comment">// State to hold the selected country, city, and other country text</span>
  <span class="hljs-keyword">const</span> [selectedCountry, setSelectedCountry] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [availableCities, setAvailableCities] = useState([]);
  <span class="hljs-keyword">const</span> [selectedCity, setSelectedCity] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [otherCountry, setOtherCountry] = useState(<span class="hljs-string">''</span>); 

  <span class="hljs-comment">// Handle country change</span>
  <span class="hljs-keyword">const</span> handleCountryChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> country = e.target.value;
    setSelectedCountry(country);
    setAvailableCities(cities[country] || []);
    setSelectedCity(<span class="hljs-string">''</span>); 
    <span class="hljs-keyword">if</span> (country !== <span class="hljs-string">'Other'</span>) {
      setOtherCountry(<span class="hljs-string">''</span>);
    }
  };

  <span class="hljs-comment">// Handle city change</span>
  <span class="hljs-keyword">const</span> handleCityChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setSelectedCity(e.target.value);
  };

  <span class="hljs-comment">// Handle other country input change</span>
  <span class="hljs-keyword">const</span> handleOtherCountryChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setOtherCountry(e.target.value);
  };

  <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">'text-center text-3xl'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-extrabold text-5xl p-10'</span>&gt;</span>Dependent Dropdown Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

      {/* Country Dropdown */}
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"country"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-bold'</span>&gt;</span>Select Country: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"country"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedCountry}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleCountryChange}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Select a country<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        {countries.map((country) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{country.id}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{country.name}</span>&gt;</span>
            {country.name}
          <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>

      {/* City or Other Country Input */}
      {selectedCountry === 'Other' ? (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"other-country"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-bold'</span>&gt;</span>Please specify the country: <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">id</span>=<span class="hljs-string">"other-country"</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{otherCountry}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleOtherCountryChange}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter country name"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      ) : (
        selectedCountry &amp;&amp; (
          <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"city"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'font-bold'</span>&gt;</span>Select City: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"city"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedCity}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleCityChange}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Select a city<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
              {availableCities.map((city, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{city}</span>&gt;</span>
                  {city}
                <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;/&gt;</span></span>
        )
      )}
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DependentDropdown;
</code></pre>
<h3 id="heading-step-3-use-the-component">Step 3: Use the Component</h3>
<p>To get your final results, you need to import the <code>DependentDropdown</code> component into your <code>App.js</code> or <code>App.jsx</code> and place it inside the return section of the App component.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> DependentDropdown <span class="hljs-keyword">from</span> <span class="hljs-string">'./DependentDropdown'</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">DependentDropdown</span>/&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Don’t forget to run the application by entering either of these commands:</p>
<pre><code class="lang-javascript">npm start <span class="hljs-comment">//for create react app</span>
npm run dev <span class="hljs-comment">//for react vite app</span>
</code></pre>
<p>Finally, this is what should render on your browser:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737899898480/38ff328c-09bd-4f74-b458-423ff1216e48.gif" alt="38ff328c-09bd-4f74-b458-423ff1216e48" class="image--center mx-auto" width="1000" height="500" loading="lazy"></p>
<h2 id="heading-handling-dynamic-data-api-requests">Handling Dynamic Data (API Requests)</h2>
<p>In real-world applications, the lists for the dropdowns might not be static. Instead, they might be fetched from an API or a JSON file acting as an API.</p>
<p>In this example, we’ll be reading data from a JSON file to populate our dependent dropdown. This practice has some benefits which are:</p>
<ul>
<li><p><strong>Reduced database load:</strong> By using a static JSON file (or a pre-loaded file), you're reducing the number of database queries that would otherwise be needed to populate dropdowns. This is especially useful if the dropdown options are fairly static and don’t change often.</p>
</li>
<li><p><strong>Faster UI rendering:</strong> Since the data is already on the client side, there’s no need for a round-trip request to the server every time the user interacts with the dropdown. This can make the interface feel more responsive.</p>
</li>
</ul>
<p>Our JSON file contains states and LGAs (Local Government Areas), which are the equivalents of Countries and Cities.</p>
<p>The data in the JSON file is represented as an array of objects, with each object having keys for <strong>state</strong>, <strong>alias</strong>, and <strong>lgas</strong>. The 'lgas' key contains an array.</p>
<p>Here’s how it’s represented:</p>
<pre><code class="lang-json">[
  {
    <span class="hljs-attr">"state"</span>: <span class="hljs-string">"Adamawa"</span>,
    <span class="hljs-attr">"alias"</span>: <span class="hljs-string">"adamawa"</span>,
    <span class="hljs-attr">"lgas"</span>: [
      <span class="hljs-string">"Demsa"</span>,
      <span class="hljs-string">"Fufure"</span>,
      <span class="hljs-string">"Toungo"</span>,
      <span class="hljs-string">"Yola North"</span>,
      <span class="hljs-string">"Yola South"</span>
    ]
  },
  {
    <span class="hljs-attr">"state"</span>: <span class="hljs-string">"Akwa Ibom"</span>,
    <span class="hljs-attr">"alias"</span>: <span class="hljs-string">"akwa_ibom"</span>,
    <span class="hljs-attr">"lgas"</span>: [
      <span class="hljs-string">"Abak"</span>,
      <span class="hljs-string">"Uruan"</span>,
      <span class="hljs-string">"Urue-Offong/Oruko"</span>,
      <span class="hljs-string">"Uyo"</span>
    ]
  },
<span class="hljs-comment">//the rest of the objects</span>
]
</code></pre>
<p>This method of creating a dynamic dependent dropdown from an API isn’t too different from the previous example, except for some minor modifications.</p>
<p>Here ‘s how we fetched and used data from a JSON file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect, 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">DependentDropdown</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">//declaring global state variables</span>
  <span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);

<span class="hljs-comment">//fetching data using the useEffect hook</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(<span class="hljs-string">"nigeria-state-and-lgas.json"</span>) <span class="hljs-comment">//JSON file set as URL</span>
      .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
      .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
        setData(data);
        setLoading(<span class="hljs-literal">false</span>);
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error fetching data:"</span>, error);
        setLoading(<span class="hljs-literal">false</span>);
      });
  }, []);
  <span class="hljs-keyword">return</span> loading ? <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<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">Form</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{data}</span> /&gt;</span></span>;

}
<span class="hljs-comment">//form recieving data as props</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Form</span>(<span class="hljs-params">{ data }</span>) </span>{

<span class="hljs-comment">//declaring local state variables</span>
  <span class="hljs-keyword">const</span> [selectedState, setSelectedState] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [selectedLga, setSelectedLga] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [showList, setShowList] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">let</span> sortedData = data.slice().sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a.state.localeCompare(b.state));
  <span class="hljs-keyword">const</span> selectedData = sortedData.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.state === selectedState);

<span class="hljs-comment">//handler function for state</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleClickState</span>(<span class="hljs-params">e</span>) </span>{
    setSelectedState(e.target.value);
    setShowList(<span class="hljs-literal">true</span>);
  }
<span class="hljs-comment">//handler function for Lga</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleClickLga</span>(<span class="hljs-params">e</span>) </span>{
    setSelectedLga(e.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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleFormSubmit}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {/* First Name */}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"firstName"</span>&gt;</span>First Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
          <span class="hljs-attr">id</span>=<span class="hljs-string">"firstName"</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"firstName"</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your first name"</span>/&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      {/* Last Name */}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"lastName"</span>&gt;</span>
          Last Name
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
          <span class="hljs-attr">id</span>=<span class="hljs-string">"lastName"</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"lastName"</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your last name"</span>/&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedState}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleClickState}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"state"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span> <span class="hljs-attr">disabled</span>&gt;</span>Choose your state<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          {sortedData.map((data) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{data.alias}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{data.state}</span>&gt;</span>
              {data.state}
            <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">div</span>&gt;</span>
      {selectedData &amp;&amp; showList &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{selectedLga}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleClickLga}</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"lga"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span> <span class="hljs-attr">disabled</span>&gt;</span>{`Choose your LGA in ${selectedState}`}<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          {selectedData.lgas.map((lgass) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{lgass}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{lgass}</span>&gt;</span>
              {lgass}
            <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">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">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>
          Submit
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DependentDropdown;
</code></pre>
<p>The key modification here is data fetching using the <code>useEffect</code> hook, which fetches the states and LGA data only on the initial render</p>
<p>Here is how this renders on the browser:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737856956995/ada964c4-a2a4-4012-869f-c0bbf53761a7.gif" alt="ada964c4-a2a4-4012-869f-c0bbf53761a7" class="image--center mx-auto" width="1000" height="500" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learnt how to create dependent dropdowns in React using both static and dynamic data. You can now use this type of dropdown in your React applications.</p>
<p>If you found this article helpful, you can connect with me on <a target="_blank" href="https://linkedin.com/in/timothy-olanrewaju750">LinkedIn</a> for more programming related articles and posts.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Django's MVT Architecture Works: A Deep Dive into Models, Views, and Templates ]]>
                </title>
                <description>
                    <![CDATA[ Django is a high-level Python framework. It’s popular for its simplicity and efficiency in building robust web applications. At the heart of Django’s architecture is the Model-View-Template (MVT) pattern. Having a good understanding of how Models, Vi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-django-mvt-architecture-works/</link>
                <guid isPermaLink="false">6758c1285b5802ad4fa00d45</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 10 Dec 2024 22:31:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733732493858/a06ee65a-de97-4c7f-b3bd-7ca8c1b6fe82.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Django is a high-level Python framework. It’s popular for its simplicity and efficiency in building robust web applications.</p>
<p>At the heart of Django’s architecture is the Model-View-Template (MVT) pattern. Having a good understanding of how Models, Views, and Templates interact is crucial if you’re looking to harness the full power of Django.</p>
<p>Whether you are completely new to Django or a beginner, this article will serve as a comprehensive guide showing you how these components work and interact with each other to create dynamic web applications.</p>
<p>To make it even more understandable, we’ll build a simple application to help you better understand the interconnectivity of these components.</p>
<p>If you’re excited already, let’s get straight into it!</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-mvt-architecture">What is the MVT Architecture?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-model-component">The Model Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-view-component">The View Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-template-component">The Template Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-diagram-showing-the-mvt-workflow">Diagram Showing the MVT WorkFlow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-analogy-of-mvt">Real-World Analogy of MVT</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-putting-it-all-together-into-a-project">Putting it All Together into a Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along, you need:</p>
<ul>
<li><p>Basic understanding of how web applications works, including client-server architecture.</p>
</li>
<li><p>Basic knowledge of Python.</p>
</li>
</ul>
<h2 id="heading-what-is-the-mvt-architecture">What is the MVT Architecture?</h2>
<p>The MVT pattern is Django’s approach to organizing the codebase and workflow of a web application. The components that make up this architecture are the Model, View, and Template. Each component performs specific functions and then passes the process to the other components to do theirs.</p>
<p>Let’s take a quick look at the components with the specific functions they perform:</p>
<ul>
<li><p><strong>Model</strong>: Also known as the data layer, it manages data and interacts with the database.</p>
</li>
<li><p><strong>View</strong>: Also known as the logic layer, it acts as the intermediary, handles logic, and manages data flow.</p>
</li>
<li><p><strong>Template</strong>: Also known as the presentation layer, it renders HTML content on the user interface.</p>
</li>
</ul>
<p>Now that you have an idea about the components and their roles in a Django application, we’ll look extensively into each component and how they interact in the architecture.</p>
<h2 id="heading-the-model-component">The Model Component</h2>
<p>Models manage the structure and interaction of data within a Django application, making them the foundation of Django apps due to the critical role data plays.</p>
<p>Django models utilize a powerful feature called <a target="_blank" href="https://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/">Object-Relational Mapping (ORM)</a>, which bridges the gap between a relational database and Python code. It converts the Python objects (classes) into database tables, their attributes into columns, and instances into rows within those tables.</p>
<p>One huge advantage of the ORM is that it allows you to interact with the database using Python objects instead of writing SQL queries. Think of it as a translator that converts one language into another for an audience to understand. In this case, the ORM translates Python code into SQL commands that the database can execute, and vice versa.</p>
<p>Django models encapsulate all database-related logic and define the structure of your database, acting as a blueprint for the data you want to store.</p>
<h3 id="heading-general-format-of-a-django-model"><strong>General format of a Django Model</strong></h3>
<p>In Django, every model follows a particular way of declaration. Here is the basic structure of a model declaration:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">model_name</span>&gt;(<span class="hljs-params">models.Model</span>):</span>
    &lt;field_name&gt; = models.&lt;field_type&gt;(&lt;optional_field_characteristics&gt;)
</code></pre>
<p>Let’s break it down:</p>
<ul>
<li><p><code>class</code>: the keyword used to define a model in Django.</p>
</li>
<li><p><code>model_name</code>: the name of the model.</p>
</li>
<li><p><code>models.Model</code>: the base class from which the model class inherits.</p>
</li>
<li><p><code>field_name</code>: the name of the database column.</p>
</li>
<li><p><code>field_type</code>: refers to the type of data the field holds like <code>charField</code>, <code>BooleanField</code> and so on.</p>
</li>
<li><p><code>optional_field_characteristics</code>: used to further define how the field behaves, like <code>max_length</code>, <code>default</code>, and so on.</p>
</li>
</ul>
<h3 id="heading-model-example"><strong>Model Example</strong></h3>
<p>Having known everything about models up to this point, we’ll construct one for a Task list. It typically contains the task title, description, and an indicator as to whether the tasks were completed or not.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Task</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">100</span>)
    description = models.TextField()
    completed = models.BooleanField(default=<span class="hljs-literal">False</span>)
</code></pre>
<p>In this model:</p>
<ul>
<li><p>Task is the name of the model.</p>
</li>
<li><p>The Task model has three fields:</p>
<ul>
<li><p><code>title</code>: A <code>CharField</code> that holds text, with a maximum length of 100 characters.</p>
</li>
<li><p><code>description</code>: A <code>TextField</code> for longer text.</p>
</li>
<li><p><code>completed</code>: A <code>BooleanField</code> that stores a <code>True</code> or <code>False</code> value, with a default of <code>False</code>.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-the-view-component">The View Component</h2>
<p>Django views are responsible for processing user requests and returning responses. They act as the bridge between the Model and the Template by collecting data from Model objects, performing logical operations on them (such as queries based on certain criteria), and then passing the data to the template for display.</p>
<p>Views can be written as functions or class-based, depending on the complexity and requirements of your application.</p>
<h3 id="heading-general-format-of-a-django-view"><strong>General Format of a Django View</strong></h3>
<p>Here is the basic structure of a View:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> &lt;<span class="hljs-title">view_name</span>&gt;(<span class="hljs-params">request</span>):</span>
    <span class="hljs-comment"># View Logic goes in here....</span>
    <span class="hljs-keyword">return</span> render(request, &lt;template&gt;, &lt;context&gt;)
</code></pre>
<p>Let’s break it down:</p>
<ul>
<li><p><code>view_name</code>: the name of the view function.</p>
</li>
<li><p><code>request</code>: the HTTP request sent by the client to the Django server, could be triggered from form submissions or clicking a button.</p>
</li>
<li><p><code>return render</code>: used to generate the HTML response. It takes:</p>
<ul>
<li><p><code>request</code>: the request object, which contains information about the incoming request.</p>
</li>
<li><p><code>template</code>: the template file to render.</p>
</li>
<li><p><code>context</code>: contains variables to be made available in the template, it usually comes in the form of a dictionary.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-view-example"><strong>View Example</strong></h3>
<p>Continuing with our Task List, this is what our view would look like:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">task_list</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-comment"># Logic goes in here...</span>
    <span class="hljs-keyword">return</span> render(request, &lt;template&gt;, {<span class="hljs-string">'tasks'</span>: tasks})
</code></pre>
<h2 id="heading-the-template-component">The Template Component</h2>
<p>Django templates are responsible for rendering the final HTML output on the browser. They define how data should be presented, by using a combination of HTML and Django’s templating language.</p>
<p>Django templating language involves using <strong>template tags</strong> <code>{% %}</code> and <strong>template variables</strong> <code>{{ }}</code> that allow you to enter Django mode in your HTML template. In this mode, you can access variables defined in your Views and use control structures within your template.</p>
<p>Templates can also be styled using CSS or any of your favorite CSS frameworks to make your user interface more presentable.</p>
<h3 id="heading-template-example"><strong>Template Example</strong></h3>
<p>Our template is a normal HTML file with Django’s templating language. Here is how our Task List template would look like:</p>
<pre><code class="lang-python">&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">"en"</span>&gt;
&lt;head&gt;
    &lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;
    &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;
    &lt;title&gt;Task List&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Task List&lt;/h1&gt;
    &lt;ul&gt;
        {% <span class="hljs-keyword">for</span> task <span class="hljs-keyword">in</span> tasks %}
            &lt;li&gt;{{ task.title }} - {{ task.completed|yesno:<span class="hljs-string">"Done,Not Done"</span> }}&lt;/li&gt;
        {% empty %}
            &lt;p&gt;No tasks available.&lt;/p&gt;
        {% endfor %}
    &lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>In this template:</p>
<ul>
<li><p>The <code>for</code> loop iterates through each task in the <code>tasks</code> list (remember it was passed as context in our views).</p>
</li>
<li><p>For each task, it outputs the task's <code>title</code> and its <code>completed</code> status (as either "Done" or "Not Done").</p>
</li>
<li><p>If the <code>tasks</code> list is empty, the <code>{% empty %}</code> block displays a fallback message saying "No tasks available."</p>
</li>
</ul>
<h2 id="heading-diagram-showing-the-mvt-workflow">Diagram Showing the MVT WorkFlow</h2>
<p>This diagram depicts how data flows within Django’s MVT architecture:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733727208715/06e27a48-ba51-421c-acc6-f0949b37a954.png" alt="MVT architecture diagram showing how data flows between client and server" class="image--center mx-auto" width="886" height="421" loading="lazy"></p>
<h2 id="heading-real-world-analogy-of-mvt">Real-World Analogy of MVT</h2>
<p>Imagine you go to a restaurant and place an order for your favorite meal. Behind the scenes, the restaurant has a recipe book that outlines how each dish should be prepared. The chef uses the recipes to prepare your meal exactly the way you ordered it. Once it's ready, the server delivers the meal to you in a presentable way.</p>
<p>Just as a chef follows the recipe to create the dish, the View uses the Model to gather and process data. Finally, like the server delivering the dish, the Template ensures the final output is presented in a clear and engaging format to the user.</p>
<h2 id="heading-putting-it-all-together-into-a-project">Putting it All Together into a Project</h2>
<p>This section will walk you through, from start to finish, how to set up the Task List we used as an example in the article. At the end, you should have a functional application with the MVT architecture in full flow.</p>
<h3 id="heading-install-python">Install Python</h3>
<p>First, ensure you have Python installed. You can visit <a target="_blank" href="https://www.python.org/downloads/">Python’s Official Website</a> to download the latest Python version.</p>
<h3 id="heading-set-up-the-django-project-and-app">Set Up the Django Project and App</h3>
<p>Next, install Django. You can install it using pip:</p>
<pre><code class="lang-bash">pip install django
</code></pre>
<p>Create a folder and open it in your favorite code editor.</p>
<p>Create a new Django project and app by running the following commands in your terminal, one after the other:</p>
<pre><code class="lang-bash">django-admin startproject myproject 
<span class="hljs-built_in">cd</span> myproject
django-admin startapp myapp
</code></pre>
<h3 id="heading-define-the-model">Define the Model</h3>
<p>In your <code>myapp/models.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Task</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">100</span>)
    description = models.TextField()
    completed = models.BooleanField(default=<span class="hljs-literal">False</span>)
</code></pre>
<h3 id="heading-create-a-form">Create a Form</h3>
<p>We need a Django form based on the Task model, so we’ll create one using the Django ModelForm.</p>
<p>In your <code>myapp</code>, create a file, name it <code>forms.py</code>, and insert this code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> forms
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Task

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskForm</span>(<span class="hljs-params">forms.ModelForm</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        model = Task
        fields = [<span class="hljs-string">'title'</span>, <span class="hljs-string">'description'</span>, <span class="hljs-string">'completed'</span>]
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>Task</code> is imported from <code>.models</code>.</p>
</li>
<li><p><code>class TaskForm(forms.ModelForm)</code>: This creates a new class called <code>TaskForm</code>, which is a subclass of <code>forms.ModelForm</code>.</p>
</li>
<li><p><code>class Meta:</code>: is a special class used by Django’s <code>ModelForm</code> to provide configuration for the form. The <code>Meta</code> class tells Django how to create the form by specifying the associated model and the fields to include in the form.</p>
</li>
<li><p><code>model = Task</code>: specifies the model that the form is based on. In this case, the form is based on the <code>Task</code> model.</p>
</li>
<li><p><code>fields = ['title', 'description', 'completed']</code>: specifies which fields from the <code>Task</code> model should be included in the form. This allows you to control which model fields appear in the form, and it can be customized to include only certain fields, rather than all fields in the model.</p>
</li>
</ul>
<h3 id="heading-create-the-view">Create the View</h3>
<p>In your <code>myapp/views.py</code>, insert this code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render,redirect
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Task
<span class="hljs-keyword">from</span> .forms <span class="hljs-keyword">import</span> TaskForm

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">task_list</span>(<span class="hljs-params">request</span>):</span>
    tasks = Task.objects.all()    <span class="hljs-comment"># Retrieve all tasks</span>

    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">'POST'</span>:    <span class="hljs-comment"># Handle form submissions</span>
        form = TaskForm(request.POST)
        <span class="hljs-keyword">if</span> form.is_valid():
            form.save()
            <span class="hljs-keyword">return</span> redirect(<span class="hljs-string">'task_list'</span>)  <span class="hljs-comment"># Redirect to avoid duplicate submissions</span>
    <span class="hljs-keyword">else</span>:
        form = TaskForm()

    <span class="hljs-comment"># Pass tasks and the form to the template</span>
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'task_list.html'</span>, {<span class="hljs-string">'tasks'</span>: tasks, <span class="hljs-string">'form'</span>: form})
</code></pre>
<p>In this view,</p>
<ul>
<li><p><code>TaskForm</code> is imported from <code>forms</code>.</p>
</li>
<li><p>The code checks if the request method is <code>POST</code>, indicating that the user has submitted a form.</p>
</li>
<li><p>If the method is <code>POST</code>, it creates an instance of <code>TaskForm</code> using the submitted data (<a target="_blank" href="http://request.POST"><code>request.POST</code></a>).</p>
</li>
<li><p>The form is then validated using <a target="_blank" href="http://form.is"><code>form.is</code></a><code>_valid()</code>, and if valid, the form is saved to the database.</p>
</li>
<li><p>After saving, the user is redirected to the task list page to prevent duplicate submissions.</p>
</li>
</ul>
<h3 id="heading-define-the-template">Define the Template</h3>
<p>In your <code>myapp</code> directory, create a <code>templates</code> folder. Inside the templates folder, create a file and name it <code>task_list.html</code>. We need to add a form element that collects the user inputs and displays them in a list on the UI.</p>
<p>In the <code>task_list</code> HTML file, we have:</p>
<pre><code class="lang-python">&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">"en"</span>&gt;
&lt;head&gt;
    &lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;
    &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;
    &lt;title&gt;Task List&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Task List&lt;/h1&gt;
    &lt;ul&gt;
        {% <span class="hljs-keyword">for</span> task <span class="hljs-keyword">in</span> tasks %}
            &lt;li&gt;{{ task.title }} - {{ task.completed|yesno:<span class="hljs-string">"Done,Not Done"</span> }}&lt;/li&gt;
        {% empty %}
            &lt;p&gt;No tasks available.&lt;/p&gt;
        {% endfor %}
    &lt;/ul&gt;

    &lt;h2&gt;Add a New Task&lt;/h2&gt;
    &lt;form method=<span class="hljs-string">"post"</span>&gt;
        {% csrf_token %}
        {{ form.as_p }}
        &lt;button type=<span class="hljs-string">"submit"</span>&gt;Add Task&lt;/button&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>In the added form code:</p>
<ul>
<li><p>We created an HTML form with the <code>POST</code> method for submitting data. It includes a <code>{% csrf_token %}</code> to protect against CSRF attacks.</p>
</li>
<li><p>The form fields are rendered using <code>{{ form.as_p }}</code>, which displays each field within a <code>&lt;p&gt;</code> tag.</p>
</li>
<li><p>Finally, a submit button labeled "Add Task" is provided, allowing the user to submit the form data.</p>
</li>
</ul>
<h3 id="heading-folder-structure">Folder Structure</h3>
<p>Having reached this point, it’s important to cross-check if you are configuring your app the right way. Here is how your folder/file structure should look like:</p>
<pre><code class="lang-python">└── 📁myproject
    └── 📁myapp
        └── 📁__pycache__
        └── 📁migrations
        └── 📁templates
            └── task_list.html
        └── __init__.py
        └── admin.py
        └── apps.py
        └── forms.py
        └── models.py
        └── tests.py
        └── urls.py
        └── views.py
    └── 📁myproject
        └── 📁__pycache__
        └── __init__.py
        └── asgi.py
        └── settings.py
        └── urls.py
        └── wsgi.py
    └── db.sqlite3
    └── manage.py
</code></pre>
<h3 id="heading-configure-the-projects-url">Configure the Project’s URL</h3>
<p>In your <code>myproject/urls.py</code>, include the URL in your <code>myapp</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path, include

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">''</span>, include(<span class="hljs-string">'myapp.urls'</span>)),
]
</code></pre>
<h3 id="heading-add-the-app-to-project-settings">Add the App to Project Settings</h3>
<p>Add your <code>myapp</code> to the list of <strong>Installed apps</strong> in your <code>myproject/settings.py</code>:</p>
<pre><code class="lang-python">INSTALLED_APPS = [
    <span class="hljs-string">'myapp'</span>,      <span class="hljs-comment"># added our myapp app</span>
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
]
</code></pre>
<h3 id="heading-run-the-server">Run the Server</h3>
<p>Apply migration and run the server by entering these commands:</p>
<pre><code class="lang-python">python manage.py migrate

python manage.py runserver
</code></pre>
<p>Visit <a target="_blank" href="http://127.0.0.1:8000/items/"><code>http://127.0.0.1:8000/</code></a> in your browser to test out your app.</p>
<h3 id="heading-final-look">Final Look</h3>
<p>Here’s how our task list app looks like on the browser after adding some tasks using the form. You can make further improvements in styling the template as you wish.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733688592866/d481df60-143e-42c7-acfe-0c329130c591.png" alt="Final task app interface" class="image--center mx-auto" width="425" height="535" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about the components in the Django’s MVT architecture, how they interact with each other, and how they make web experiences seamless. We also built a simple project to see how it works practically, and I hope you understand it better now.</p>
<p>If you enjoyed reading this article, you can follow me on <a target="_blank" href="https://x.com/SmoothTee_DC">X</a> or connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> for more programming articles and posts.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Meme Generator Using HTML Canvas ]]>
                </title>
                <description>
                    <![CDATA[ We all come across memes almost every day on the internet. Whether you're scrolling through social media or chatting with friends, there's a good chance you'll stumble on a meme, or even share one yourself. A meme can be an image, a video, or gif tha... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-meme-generator-using-html-canvas/</link>
                <guid isPermaLink="false">673c929fd0881b2b1feaf916</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 19 Nov 2024 13:29:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731783150771/d3ba743f-c945-482e-a25d-9d093c7e866b.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We all come across memes almost every day on the internet. Whether you're scrolling through social media or chatting with friends, there's a good chance you'll stumble on a meme, or even share one yourself. A meme can be an image, a video, or gif that is meant to be funny or convey a message in a lighthearted way.</p>
<p>Memes are fun and we all love them. What if I told you that you can create yours from scratch? Well, that is what I’ll be showing you in this article using HTML Canvas. No need for fancy software - just a little code and some creativity to make your own custom memes.</p>
<p>If you are excited about this, let’s jump straight into it!</p>
<h2 id="heading-what-youll-need">What You’ll Need</h2>
<p>To follow along with this tutorial, you will need:</p>
<ul>
<li><p>Basic knowledge of HTML, CSS and JavaScript.</p>
</li>
<li><p>A text Editor (like Visual Studio Code or Sublime Text).</p>
</li>
<li><p>A modern web browser.</p>
</li>
</ul>
<h2 id="heading-step-one-set-up-your-project">Step One: Set Up your Project</h2>
<p>Create a folder and create these three files in the folder:</p>
<ul>
<li><p><code>Index.html</code></p>
</li>
<li><p><code>Style.css</code></p>
</li>
<li><p><code>Script.js</code></p>
</li>
</ul>
<h2 id="heading-step-two-html-structure">Step Two: HTML Structure</h2>
<p>First, let’s create the basic structure of the HTML file. Our structure would include a file upload button for images, a text input for adding captions (both at the top and bottom), buttons to generate and download the meme and a canvas for displaying the image and caption(s).</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Meme Generator<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"style.css"</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">h1</span>&gt;</span>Meme Generator<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"imageInput"</span> <span class="hljs-attr">accept</span>=<span class="hljs-string">"image/*"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"controls"</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">id</span>=<span class="hljs-string">"topText"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter Top Text"</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">id</span>=<span class="hljs-string">"bottomText"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter Bottom Text"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"generate"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"generateMeme()"</span>&gt;</span>Generate Meme<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">id</span>=<span class="hljs-string">"download"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"downloadMeme()"</span>&gt;</span>Download Meme<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"memeCanvas"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"580"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"450"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"script.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">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-step-three-styling-with-css">Step Three: Styling with CSS</h2>
<p>Next, we apply styling to the HTML elements we just created to make it more appealing and user-friendly. Here, we just apply basic CSS to center the content and add colors to both the background and buttons.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">121</span>, <span class="hljs-number">121</span>, <span class="hljs-number">170</span>);
    <span class="hljs-attribute">color</span>: white;
}
<span class="hljs-selector-tag">canvas</span> {
    <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#333</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
}
<span class="hljs-selector-class">.controls</span> {
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
}
<span class="hljs-selector-class">.controls</span> <span class="hljs-selector-tag">input</span>, <span class="hljs-selector-class">.controls</span> <span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span>;
}
<span class="hljs-selector-id">#generate</span>{
    <span class="hljs-attribute">background-color</span>: green;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">font-weight</span>: bold;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">6px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
}
<span class="hljs-selector-id">#download</span>{
    <span class="hljs-attribute">background-color</span>: blue;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">font-weight</span>: bold;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">6px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>Here's how our webpage looks in the browser after applying the styling:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731772678380/edd33637-73dd-40b6-8b8d-352d350ac52e.png" alt="meme generator page on the browser" class="image--center mx-auto" width="1364" height="644" loading="lazy"></p>
<h2 id="heading-step-four-add-javascript-to-handle-logic">Step Four: Add JavaScript to Handle Logic</h2>
<p>Now, let’s code the functionalities of our app using JavaScript.</p>
<h3 id="heading-initialization">Initialization</h3>
<p>First, we need to initialize some important elements that would enable us render our image on the canvas.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'memeCanvas'</span>);
<span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>);
<span class="hljs-keyword">const</span> imageInput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'imageInput'</span>);
<span class="hljs-keyword">let</span> uploadedImage = <span class="hljs-literal">null</span>;
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>canvas</code>: Refers to the HTML <code>&lt;canvas&gt;</code> element with the ID of <code>memeCanvas</code>. This is where the meme image and text will be drawn.</p>
</li>
<li><p><code>ctx</code>: While using canvas, there are methods that can be applied that enables for drawing shapes, images and texts on the canvas. We specified a <em>Context-Type</em> of <strong>2d</strong>, making the canvas render in 2D context.</p>
</li>
<li><p><code>imageInput</code>: Refers to an <code>&lt;input&gt;</code> element of type <code>file</code> (with the ID of <code>imageInput</code>) that allows you upload an image.</p>
</li>
<li><p><code>uploadedImage</code>: A variable to store the uploaded images so it can be drawn on the canvas.</p>
</li>
</ul>
<h3 id="heading-how-to-upload-images">How to Upload Images</h3>
<p>Next, we want to be able to choose a particular file, read it and draw the selected image file on the canvas.</p>
<p>Our meme generator will accept only files with a <code>type</code> of <code>image</code><strong>.</strong></p>
<pre><code class="lang-javascript">imageInput.addEventListener(<span class="hljs-string">'change'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> file = event.target.files[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">const</span> reader = <span class="hljs-keyword">new</span> FileReader();

  reader.onload = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> img = <span class="hljs-keyword">new</span> Image();
    img.src = e.target.result;
    img.onload = <span class="hljs-function">() =&gt;</span> {
      uploadedImage = img;
      drawImage();
    };
  };

  reader.readAsDataURL(file);
});
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>imageInput.addEventListener('change')</code>: Adds and listens for a <code>change</code> event to the file input field that triggers when the user selects a file.</p>
</li>
<li><p><a target="_blank" href="http://event.target"><code>event.target</code></a><code>.files[0]</code>: Accesses the first file the user selects.</p>
</li>
<li><p><code>FileReader</code>: Reads file data and allows it to be accessed as a URL.</p>
</li>
<li><p><code>reader.onload</code>: This function is triggered after the file is read. It does the following:</p>
<ul>
<li><p>Creates a new <code>Image</code> object.</p>
</li>
<li><p>Sets the image’s <code>src</code> property to the file's data URL.</p>
</li>
<li><p>Waits for the image to load and then:</p>
<ul>
<li><p>Stores the image in the <code>uploadedImage</code> variable.</p>
</li>
<li><p>Calls <code>drawImage()</code> to draw the image on the canvas.</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="heading-how-to-draw-the-image-and-text-caption">How to Draw the Image and Text Caption</h3>
<p>Here, we’ll be drawing the image, fixing the captions inputted by the user on top of the image (overlay), and styling and positioning the text captions.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawImage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (uploadedImage) {
    <span class="hljs-comment">// Clear canvas and set canvas dimensions to fit the image</span>
    ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
    ctx.drawImage(uploadedImage, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

    <span class="hljs-comment">// Get text values</span>
    <span class="hljs-keyword">const</span> topText = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'topText'</span>).value;
    <span class="hljs-keyword">const</span> bottomText = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'bottomText'</span>).value;

    <span class="hljs-comment">// Set text styles</span>
    ctx.font = <span class="hljs-string">'30px Impact'</span>;
    ctx.fillStyle = <span class="hljs-string">'white'</span>;
    ctx.strokeStyle = <span class="hljs-string">'black'</span>;
    ctx.lineWidth = <span class="hljs-number">2</span>;
    ctx.textAlign = <span class="hljs-string">'center'</span>;

    <span class="hljs-comment">// Draw top text</span>
    ctx.fillText(topText, canvas.width / <span class="hljs-number">2</span>, <span class="hljs-number">50</span>);
    ctx.strokeText(topText, canvas.width / <span class="hljs-number">2</span>, <span class="hljs-number">50</span>);

    <span class="hljs-comment">// Draw bottom text</span>
    ctx.fillText(bottomText, canvas.width / <span class="hljs-number">2</span>, canvas.height - <span class="hljs-number">20</span>);
    ctx.strokeText(bottomText, canvas.width / <span class="hljs-number">2</span>, canvas.height - <span class="hljs-number">20</span>);
  }
}
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>ctx.clearRect(0, 0, canvas.width, canvas.height)</code>: Clears the canvas so it can be redrawn.</p>
</li>
<li><p><code>ctx.drawImage()</code>: Draws the uploaded image on the canvas and stretches it to fit the set dimensions.</p>
</li>
<li><p><code>topText</code> and <code>bottomText</code>: Captures the user’s input from two text fields – <code>&lt;input id="topText"&gt;</code> and <code>&lt;input id="bottomText"&gt;</code>.</p>
</li>
</ul>
<p><strong>Text styling</strong>:</p>
<ul>
<li><p><code>ctx.font</code>: Sets the font style.</p>
</li>
<li><p><code>ctx.fillStyle</code>: Sets the fill color for the text.</p>
</li>
<li><p><code>ctx.strokeStyle</code>: Sets the outline color for the text.</p>
</li>
<li><p><code>ctx.lineWidth</code>: Sets the thickness of the outline.</p>
</li>
<li><p><code>ctx.textAlign</code>: Ensures text is centered relative to the X-coordinate.</p>
</li>
<li><p><code>ctx.fillText()</code> and <code>ctx.strokeText()</code>:</p>
<ul>
<li><p>Draws the text at specified positions.</p>
</li>
<li><p><code>canvas.width / 2</code> ensures text is horizontally centered.</p>
</li>
<li><p><code>50</code> and <code>canvas.height - 20</code> define vertical positions for the top and bottom text.</p>
</li>
</ul>
</li>
</ul>
<p>You can customize the text styling to your liking.</p>
<h3 id="heading-how-to-generate-the-meme">How to Generate the Meme</h3>
<p>Next, we’ll trigger the function that generates the meme by drawing user-provided text on the image.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateMeme</span>(<span class="hljs-params"></span>) </span>{
  drawImage();
}
</code></pre>
<p>The code above calls the <code>drawImage</code> function to ensure that the canvas is updated with the image and user-entered text.</p>
<h3 id="heading-how-to-download-the-meme">How to Download the Meme</h3>
<p>Finally, we want to be able to download our meme as an image into our device. Here is how we can achieve that:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">downloadMeme</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> link = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'a'</span>);
  link.download = <span class="hljs-string">'meme.png'</span>;
  link.href = canvas.toDataURL();
  link.click();
}
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>document.createElement('a')</code>: Creates a temporary <code>&lt;a&gt;</code> element.</p>
</li>
<li><p><a target="_blank" href="http://link.download"><code>link.download</code></a> <code>= 'meme.png'</code>: Sets the file name for the downloaded meme (every meme you download will carry the name of <code>meme.png</code> – you can change it if you wish to).</p>
</li>
<li><p><code>link.href = canvas.toDataURL()</code>: Converts the canvas content into a Data URL.</p>
</li>
<li><p><a target="_blank" href="http://link.click"><code>link.click</code></a><code>()</code>: Simulates a click on the link, triggering the download.</p>
</li>
</ul>
<p>With this, we now have a fully functional meme generator.</p>
<h3 id="heading-full-javascript-code">Full JavaScript Code</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'memeCanvas'</span>);
<span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>);
<span class="hljs-keyword">const</span> imageInput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'imageInput'</span>);
<span class="hljs-keyword">let</span> uploadedImage = <span class="hljs-literal">null</span>;

<span class="hljs-comment">// Load the image onto the canvas</span>
imageInput.addEventListener(<span class="hljs-string">'change'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> file = event.target.files[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">const</span> reader = <span class="hljs-keyword">new</span> FileReader();

  reader.onload = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> img = <span class="hljs-keyword">new</span> Image();
    img.src = e.target.result;
    img.onload = <span class="hljs-function">() =&gt;</span> {
      uploadedImage = img;
      drawImage();
    };
  };

  reader.readAsDataURL(file);
});

<span class="hljs-comment">// Draw image and text on canvas</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawImage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (uploadedImage) {
    <span class="hljs-comment">// Clear canvas and set canvas dimensions to fit the image</span>
    ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
    ctx.drawImage(uploadedImage, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

    <span class="hljs-comment">// Get text values</span>
    <span class="hljs-keyword">const</span> topText = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'topText'</span>).value;
    <span class="hljs-keyword">const</span> bottomText = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'bottomText'</span>).value;

    <span class="hljs-comment">// Set text styles</span>
    ctx.font = <span class="hljs-string">'30px Impact'</span>;
    ctx.fillStyle = <span class="hljs-string">'white'</span>;
    ctx.strokeStyle = <span class="hljs-string">'black'</span>;
    ctx.lineWidth = <span class="hljs-number">2</span>;
    ctx.textAlign = <span class="hljs-string">'center'</span>;

    <span class="hljs-comment">// Draw top text</span>
    ctx.fillText(topText, canvas.width / <span class="hljs-number">2</span>, <span class="hljs-number">50</span>);
    ctx.strokeText(topText, canvas.width / <span class="hljs-number">2</span>, <span class="hljs-number">50</span>);

    <span class="hljs-comment">// Draw bottom text</span>
    ctx.fillText(bottomText, canvas.width / <span class="hljs-number">2</span>, canvas.height - <span class="hljs-number">20</span>);
    ctx.strokeText(bottomText, canvas.width / <span class="hljs-number">2</span>, canvas.height - <span class="hljs-number">20</span>);
  }
}

<span class="hljs-comment">// Generate meme by drawing text on the uploaded image</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateMeme</span>(<span class="hljs-params"></span>) </span>{
  drawImage();
}

<span class="hljs-comment">// Download the meme as an image</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">downloadMeme</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> link = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'a'</span>);
  link.download = <span class="hljs-string">'meme.png'</span>;
  link.href = canvas.toDataURL();
  link.click();
}
</code></pre>
<h3 id="heading-steps-on-creating-your-meme-on-meme-generator">Steps on Creating your Meme on Meme Generator</h3>
<ul>
<li><p>Click on the <strong>Browse</strong> button and select a particular image.</p>
</li>
<li><p>Enter text into either of the two input types – labelled Top and Bottom Text.</p>
</li>
<li><p>Click on <strong>Generate Meme</strong> button to create your meme.</p>
</li>
<li><p>Click on <strong>Download Meme</strong> to download your generated meme.</p>
</li>
</ul>
<p>This is the meme generator in full action with the steps demonstrated:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731787007980/24206a68-6e2e-4883-81f2-1db5169cb093.gif" alt="Meme Generator project working in the browser" class="image--center mx-auto" width="1152" height="648" loading="lazy"></p>
<h3 id="heading-final-results">Final Results</h3>
<p>Here are two memes created by our meme generator.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731780897736/d136df1d-c3a4-416d-90ca-e6e400d10a0e.png" alt="meme 1" class="image--center mx-auto" width="580" height="450" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731780929605/f67cc533-2bb4-4bdb-ad9f-1231caede069.png" alt="meme 2" class="image--center mx-auto" width="580" height="450" loading="lazy"></p>
<p>Pretty cool right?</p>
<p>Now, you can try it out and create your own viral meme!</p>
<p>For more programming articles and posts, you can follow me on <a target="_blank" href="https://x.com/SmoothTee_DC">X</a> or connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a>.</p>
<p>See you in the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Skeleton Screens to Improve Perceived Website Performance ]]>
                </title>
                <description>
                    <![CDATA[ When you’re building a website, it’s important to make sure that it’s fast. People have little to no patience for slow-loading websites. So as developers, we need to use all the techniques available to us to speed up our site’s performance. And somet... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-skeleton-screens-to-improve-perceived-website-performance/</link>
                <guid isPermaLink="false">671955939f7c056f46dd8604</guid>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Wed, 23 Oct 2024 19:59:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729603651952/5f5f3c38-20e0-41ac-a4a0-7190347b3a59.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you’re building a website, it’s important to make sure that it’s fast. People have little to no patience for slow-loading websites. So as developers, we need to use all the techniques available to us to speed up our site’s performance.</p>
<p>And sometimes, we need to make users think that something is happening when they’re waiting for a page to load so they don’t give up and leave the site.</p>
<p>Fast webpage loading speed is important these days because humans’ attention spans are shrinking. According to <a target="_blank" href="https://www.wellbrookrecovery.com/post/average-attention-span">statistics on the average human attention span</a>, the average page visit lasts less than a minute, with users often leaving web pages in just 10-20 seconds.</p>
<p>This means that we as developers have had to come up with strategies to keep users engaged while waiting for their requested web page content to load. And this led to the concept of the Skeleton Screen.</p>
<p>In this article, we’ll be looking at what skeleton screens are, how effective they are at enhancing the user experience and build a skeleton screen of our own !. </p>
<h2 id="heading-what-is-a-skeleton-screen"><strong>What is a Skeleton Screen?</strong></h2>
<p>A skeleton screen is like a sketch of a webpage that displays before the final page fully loads. It gives you a glimpse of the form and positioning of elements on your screen (like text, images, and buttons) which are represented by a placeholder.</p>
<p>Here is what a YouTube skeleton screen looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729602784479/b4ffa403-f642-41f0-911b-897f2eebad2b.png" alt="YouTube skeleton screen example showing placeholders" class="image--center mx-auto" width="1357" height="561" loading="lazy"></p>
<p>When you visit a website that uses skeleton screens, the skeleton screen appears first while the content is being fetched. When the content finally gets fetched, it gradually replaces the skeleton screen until the screen is fully populated.</p>
<p>That is what brought about the name <em>Skeleton Screen</em> – because the bare bones akin to a skeleton appear first before being fleshed out by real content.</p>
<p>Skeleton screens take the appearance or form of elements they are meant to “stand in place of” – meaning oval-shaped placeholders are replaced by oval-shaped elements on full loading, and so on. </p>
<p>The ultimate goal of the skeletal screen is to make the waiting game less painful by giving users something to focus on. It has nothing to do with actual load time but all to do with providing a distraction so the waiting time feels shorter. It can also reassure users that content is indeed coming. Clever right?</p>
<h2 id="heading-the-psychology-behind-skeleton-screens"><strong>The Psychology Behind Skeleton Screens</strong></h2>
<p>Here is where things get interesting. You might already be wondering what the reasoning behind such an invention was.</p>
<p>Based on what we’ve already discussed, you probably agree that they are all about “Perceived Performance”. It’s less about how long users have to wait and more about how long it <em>feels</em> like they’re waiting.</p>
<p>If you’ve ever been stuck in traffic, you’d know there is a difference in feeling when you’re moving forward versus sitting still. Moving traffic, even if it’s slow, is better than being stuck in a total gridlock.</p>
<p>The same applies to a user who’s visiting a webpage. A visible and engaging placeholder is better than being greeted with a blank screen while waiting for the final content to show.</p>
<p>With skeleton screens, it's like “Hey, here is the form of the page content you’re looking for, but please, exercise some patience while we get you the real thing!”</p>
<p>This fits perfectly into the <strong>Zeigarnik Effect</strong>, a psychological principle suggesting that we remember incomplete tasks better than completed ones. Think of it like leaving a jigsaw puzzle half-finished on your table – your brain stays engaged, eager to see the final picture.</p>
<p>Similarly, when users see a skeleton screen, they remain mentally hooked, anticipating the moment when the content will fully load.</p>
<h2 id="heading-skeleton-screens-vs-spinners-and-progress-bars"><strong>Skeleton Screens vs Spinners and Progress Bars</strong></h2>
<p>Spinners and progress bars might seem like a viable alternative to skeleton screens, but do they have the same effect on users? The answer is – not quite.</p>
<p>With spinners and progress bars, the load time is somewhat undecided, and it’s a bit like watching a clock tick – the time seems to move slower, as focusing on the hands of the clock makes the duration seem longer and more frustrating.</p>
<p>Skeleton screens, on the other hand, add an interesting extra layer of providing a visual cue of expected content rather than just displaying an indicator (which is what spinners and progress bars do).</p>
<p>Interfaces that use skeleton screens make the user scan the screen thinking things like, “That rectangle must be an image or video, and these blocks look like they are for text”. They don’t leave users idle but keep their brains and eyes engaged.</p>
<h2 id="heading-is-a-skeleton-screen-just-a-visual-illusion"><strong>Is a Skeleton Screen Just a Visual Illusion?</strong></h2>
<p>Yes, skeleton screens are a bit of an illusion. They don’t speed up load times – rather, they just make it feel faster.</p>
<p>But here’s the thing: if not done well, this trick can backfire. Users expect that once they see the skeleton screen, the real content should follow quickly. If not frustration creeps in.</p>
<p>Also, adding motion to skeleton screens makes the illusion effect more effective by decreasing the perceived duration time. It is not uncommon to see sliding effects (left to right) and pulse effects (fading opacity – in and out) used in skeleton screens.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729603561030/235b53ed-a75d-4eb0-9126-c63174d0c59f.gif" alt="skeleton screen with motion" class="image--center mx-auto" width="400" height="300" loading="lazy"></p>
<p>Finally, for best results, skeleton screens should be neutral in color. This is important as it helps to create a smooth and subtle loading experience without distracting or overwhelming users.</p>
<h2 id="heading-how-to-build-a-skeleton-screen-with-react">How to Build a Skeleton Screen with React</h2>
<p>Now that you know what a skeleton screen is all about, let’s build our own using React.</p>
<h3 id="heading-step-1-set-up-your-react-project"><strong>Step 1: Set up Your React Project</strong></h3>
<p>If you’re new to React and wish to follow along, click this <a target="_blank" href="https://vite.dev/guide/">link</a> and follow the steps to create your React project. When you’re done, come back here and let’s continue building.</p>
<p>If you already have a React project you want to use, that’s great, too.</p>
<h3 id="heading-step-2-install-react-loading-skeleton-package"><strong>Step 2: Install</strong> <code>react-loading-skeleton</code> <strong>Package</strong></h3>
<p>Next, we’ll install a package called <strong>react-loading-skeleton</strong> that helps in creating beautiful and animated skeletons. To install this package:</p>
<ul>
<li><p>Navigate to your project on your terminal.</p>
</li>
<li><p>If you’re using yarn, type this command <code>yarn add react-loading-skeleton</code> or <code>npm install react-loading-skeleton</code> for npm users.</p>
</li>
</ul>
<h3 id="heading-step-3-how-to-handle-states-and-skeleton-imports"><strong>Step 3: How to Handle States and Skeleton Imports</strong></h3>
<p>There are variables that will be changing frequently in our project, and they need to be declared. You can read my article on <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/">state management</a> if you are not familiar with the concept.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
  <span class="hljs-keyword">import</span> Skeleton <span class="hljs-keyword">from</span> <span class="hljs-string">'react-loading-skeleton'</span>;
  <span class="hljs-keyword">import</span> <span class="hljs-string">'react-loading-skeleton/dist/skeleton.css'</span>;

  <span class="hljs-keyword">const</span> SkeletonScreenComponent = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [data, setData] = useState([]);
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);
  }
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SkeletonScreenComponent;
</code></pre>
<p>In this code, we declared three states in our <strong>SkeletonScreenComponent</strong> which are:</p>
<ul>
<li><p><strong>data</strong>: responsible for storing the data fetched from a fake REST API with its initial value set to an empty array.</p>
</li>
<li><p><strong>loading</strong>: to keep track of data loading with its initial value set to a Boolean value of <strong>true</strong>.</p>
</li>
<li><p><strong>error</strong>: to store any error message with initial value set to <strong>null.</strong></p>
</li>
</ul>
<p>We also imported the <code>useState</code> hook for the states together with the <code>Skeleton</code> component and its CSS from the <code>react-loading-skeleton</code> library.</p>
<h3 id="heading-step-4-fetch-data-from-the-fake-api"><strong>Step 4: Fetch Data from the Fake API</strong></h3>
<p>Our little project will be fetching data from <a target="_blank" href="https://jsonplaceholder.typicode.com/posts">https://jsonplaceholder.typicode.com/posts</a>, which is a free online fake REST API.</p>
<pre><code class="lang-javascript">  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchData();
  }, []);

  <span class="hljs-keyword">const</span> fetchData = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts'</span>);
        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network response was not ok'</span>);
        }
        <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> response.json();
        setData(result);
        setLoading(<span class="hljs-literal">false</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      setError(<span class="hljs-string">'Error fetching data'</span>+ err.message);
      setLoading(<span class="hljs-literal">false</span>);
    } 
  };
</code></pre>
<p>In the code block above:</p>
<ul>
<li><p>The <strong>useEffect hook</strong> is responsible for handling side effects. It’s perfect for data fetching purposes, and has its dependency array set to empty (makes it render on mount).</p>
</li>
<li><p><strong>fetchData</strong> is an asynchronous function that fetches data from the <strong>URL</strong>, updates the <strong>data</strong> state, sets <strong>loading</strong> state to false when done, catches any errors, and updates the <strong>error</strong> state.</p>
</li>
</ul>
<h3 id="heading-step-5-conditional-rendering"><strong>Step 5: Conditional Rendering</strong></h3>
<p>The whole idea of this project revolves around the <strong>loading</strong> state. The component renders different content based on the <strong>loading</strong> state.</p>
<p>If <strong>loading</strong> is true:</p>
<ul>
<li><p>An Array is created where each element is a Skeleton component.</p>
</li>
<li><p>The <strong>Skeleton count</strong> is set to 2, for the post title and body. You can set the count according to the number of placeholders you want to display.</p>
</li>
</ul>
<p>If data loading is successful:</p>
<ul>
<li><p>It maps through the <strong>data</strong> array.</p>
</li>
<li><p>It renders each post’s title and body.</p>
</li>
</ul>
<p>If there is an error, an error message is displayed.</p>
<pre><code class="lang-javascript">   <span class="hljs-keyword">if</span> (loading) {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {Array.from({ length: 15 },(_, 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">style</span>=<span class="hljs-string">{{</span>  <span class="hljs-attr">marginTop:</span> '<span class="hljs-attr">30px</span>'  }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Skeleton</span> <span class="hljs-attr">count</span>=<span class="hljs-string">{2}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{marginBottom:</span>"<span class="hljs-attr">5px</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">if</span> (error) {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{error}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {data.map(({id, title, body}) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginBottom:</span> '<span class="hljs-attr">20px</span>' }}&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{body}<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>
<h3 id="heading-final-result"><strong>Final Result</strong></h3>
<p>This is what our Skeleton screen looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729711380366/974d0de9-faf1-4050-90e7-1c982ac72e67.gif" alt="974d0de9-faf1-4050-90e7-1c982ac72e67" class="image--center mx-auto" width="1536" height="864" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Skeleton screens are great at creating the illusion of progress and making users feel like the site is loading faster. But they don’t fix slow-loading pages on their own. The trick is combining skeleton screens with performance-enhancing techniques such as lazy loading, image compression, and server-side rendering.</p>
<p>Balancing the actual speed and the user’s perception of it is vital in web performance. Skeleton screens are just one tool in your UX toolbox – but when used correctly, they can help create a web experience that feels fast, reliable, and most importantly engaging. And in the world of web development, where perception is reality, that’s half the battle won.</p>
<p>For more front-end related posts and articles, you can follow me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> and <a target="_blank" href="https://x.com/SmoothTee_DC">X</a>.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use CDNs to Improve Performance in your Front-end Projects ]]>
                </title>
                <description>
                    <![CDATA[ In web development, styling plays a crucial role in the visual presentation of web applications. According to a study by Adobe, 59% of users would choose a beautifully designed website over a “simple and plain” design. So designs that are crafted in ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-cdns-improve-performance-in-front-end-projects/</link>
                <guid isPermaLink="false">670d72a6d4c1491e5ee9df77</guid>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CDN ]]>
                    </category>
                
                    <category>
                        <![CDATA[ computer networking ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 14 Oct 2024 19:36:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728820334493/8ef2738f-c2ac-42d3-be3f-5a6a3bddbdbd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In web development, styling plays a crucial role in the visual presentation of web applications. According to a study by Adobe, 59% of users would choose a beautifully designed website over a “simple and plain” design. So designs that are crafted in a visually appealing way tend to attract users to consume content on a website.</p>
<p>In recent times, there has been a steady rise in styling tools that you can use to elevate the visual appeal of your websites. Such tools include CSS frameworks, animation libraries, icon libraries, and typography libraries. These tools offer customization flexibility, responsiveness, and consistency.</p>
<p>One awesome thing about these styling tools is that they bundle stylistic effects in a file which you can access via a Content Delivery Network (CDN).</p>
<p>In this article, we’ll be looking extensively at CDNs, how they work, their different hosting methods, the differences between them, their pros and cons, and the best use-cases of the methods for your project.</p>
<p>Let's dive straight into it!</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-cdn">What is a CDN?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-does-a-cdn-work">How does a CDN work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-analogy-to-explain-cdns">Real-world analogy to explain CDNs</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-why-are-cdns-important">Why are CDNs Important?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-different-ways-to-use-a-cdn">Different Ways to Use a CDN</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-remote-hosted-cdn">Remote Hosted CDN</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-locally-hosted-cdn">Locally Hosted CDN</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hybrid-hosted-cdn">Hybrid Hosted CDN</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-cdn"><strong>What is a CDN?</strong></h2>
<p>A CDN, or Content Delivery Network, is a system of distributed servers that delivers web content (like images, stylesheets, scripts and other resources) to users, reliably and efficiently.</p>
<h3 id="heading-how-does-a-cdn-work"><strong>How does a CDN work?</strong></h3>
<p>A CDN’s primary function is to cache and serve both static and dynamic web content to users. It achieves this by using the following:</p>
<ul>
<li><p><strong>Origin Server</strong>: This is the main server where all content is originally hosted.</p>
</li>
<li><p><strong>Edge Servers</strong>: These are servers distributed in different geographical locations to serve web content to users closer to them.</p>
</li>
<li><p><strong>Caching</strong>: This is a way of storing content on edge servers to reduce repeated requests to the origin server.</p>
</li>
<li><p><strong>DNS Routing</strong>: This is the mechanism that reroutes users to the nearest edge servers based on their location.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728819505243/6389ac39-e1d2-4348-9f97-8ee370eecd7f.png" alt="Diagram showing origin server communicating with different edge servers" class="image--center mx-auto" width="1600" height="900" loading="lazy"></p>
<p>This is what happens when a user clicks on a CDN link:</p>
<ul>
<li><p>If trying to access the resource for the first time, the request hits the origin server.</p>
</li>
<li><p>The origin server sends the resource to the user as a response and also sends a copy to the edge server located geographically closest to the user.</p>
</li>
<li><p>The edge server caches the copy.</p>
</li>
<li><p>When the user wants to access the resources again, the edge server (not the origin server) sends over the cached copy.</p>
</li>
</ul>
<h3 id="heading-real-world-analogy-to-explain-cdns"><strong>Real-World Analogy to Explain CDNs</strong></h3>
<p>To further explain how the CDN works, I’ll give an analogy to make it clearer. Imagine having an account with a bank that has its headquarters in New York (origin server).</p>
<p>You don’t expect customers who live far away from New York to be scampering to the headquarters any time they encounter issues. Instead, the bank provides branches (edge servers) in different locations to cater to the needs of their customers. Customers can easily walk into any branch nearest to them and get their issues or transactions sorted.</p>
<p>The branches have every customer's account information and transaction logs (cached data). Every branch of that bank delivers the same services and can satisfy their customers regardless of their distance from the headquarters.</p>
<p>The distribution of branches in different locations helps reduce the traffic that would have caused delays if the bank had just the headquarters as the only option. On contacting the bank's customer service on an issue, you would most likely be redirected to the nearest bank branch to you (DNS Routing)!</p>
<h2 id="heading-why-are-cdns-important"><strong>Why are CDNs Important?</strong></h2>
<p>There are many reasons why CDNs many websites use CDNs these days. Some of the key benefits are:</p>
<ol>
<li><p><strong>Improved Website Performance:</strong> CDNs can compress files and optimize images automatically, which helps speed up load time.</p>
</li>
<li><p><strong>Efficient Resource Storage:</strong> With CDNs, styling resources are stored and managed properly. Resources are also stored in files matching their content types.</p>
</li>
<li><p><strong>Better Search Engine Optimization (SEO):</strong> Using CDNs directly speeds up load time which in turn impacts search engine rankings. Google considers site speed a key metric that allows web pages to show up higher in search engines.</p>
</li>
<li><p><strong>Better User Experience:</strong> Users prefer faster and more responsive websites to slow and unresponsive ones. With a better user experience, a website is sure to receive more engagement and lower bounce rates.</p>
</li>
</ol>
<h2 id="heading-different-ways-to-use-a-cdn"><strong>Different Ways to Use a CDN</strong></h2>
<p>There are three ways you can access CDN resources in your project:</p>
<ul>
<li><p>Remote Hosting</p>
</li>
<li><p>Local Hosting</p>
</li>
<li><p>Hybrid Hosting</p>
</li>
</ul>
<h3 id="heading-remote-hosted-cdn"><strong>Remote Hosted CDN</strong></h3>
<p>Remote CDN links allow developers to access styling resources from a third-party server by simply linking to the CDN in their HTML files via the <code>link</code> or <code>script</code> tag.</p>
<p>Bootstrap, for example, has two primary CDN links – one for CSS stylesheet and another for JavaScript (handles dynamic interaction like dropdowns, pop-overs, and so on).</p>
<p>To use a Bootstrap stylesheet in your project, you need to add this single line - <code>https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css</code></p>
<p>And for the JavaScript: <code>https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js</code></p>
<h4 id="heading-how-to-find-remote-cdn-links"><strong>How to find remote CDN links</strong></h4>
<p>The best way to identify thte remote CDN links of your desired styling tool is to visit their official documentation site and look for the direct links there.</p>
<h4 id="heading-advantages-of-a-remote-cdn"><strong>Advantages of a remote CDN:</strong></h4>
<ol>
<li><p><strong>Easy to Use:</strong> You don’t need to download, manage, or upload files with CDN links. All you need to do is insert a single line of code in your HTML file and you are good to go.</p>
</li>
<li><p><strong>Global Caching:</strong> whenever you visit a website that uses CDN links, it downloads the resources on loading the page and then saves it in your browser cache. On subsequent visits to the same website or other sites that use the same CDN, it fetches from the cache and displays these resources more quickly. This is one of the biggest advantages of using CDN links, as it improves website load time.</p>
</li>
<li><p><strong>Optimized Global Delivery:</strong> CDNs are built to deliver content to users around the world by serving files from edge servers closest to users. This helps reduce the time it takes data to transfer across a network, also known as latency, and boosts performance for international users.</p>
</li>
<li><p><strong>Reduced Server Load:</strong> Due to the CDN fetching data from an external source, the load on your server is reduced, which is helpful for high-traffic websites.</p>
</li>
<li><p><strong>Real-Time Updates:</strong> Companies that own CDN links carry out periodic bug fixing, security patching, and feature updates, which can be beneficial for your project. These updates are reflected as soon as they are released.</p>
</li>
</ol>
<h4 id="heading-disadvantages-of-a-remote-cdn"><strong>Disadvantages of a remote CDN:</strong></h4>
<ol>
<li><p><strong>Customization Limitations:</strong> Styling components in remote CDNs are standard and unmodified. To modify them, you would have to override the specific styles in your local file which can introduce complexities.</p>
</li>
<li><p><strong>No Control over Updates:</strong> When automatic updates are made, they can cause problems in your web applications. If the changes being introduced include drastic changes, it can affect your website’s layout or behavior in a big way.</p>
</li>
<li><p><strong>Dependency on Third-Party Availability:</strong> If the CDN service experiences hitches like downtime or slowness, it can lead to broken styles thus, affecting your site’s performance negatively.</p>
</li>
<li><p><strong>Privacy and Security Concerns:</strong> Links referencing an external source can pose serious security concerns, as they can be used to track users and get vital information. It is important to include only trusted CDN link sources in your web project to avoid breaches.</p>
</li>
</ol>
<h3 id="heading-locally-hosted-cdn"><strong>Locally Hosted CDN</strong></h3>
<p>These are CDN resources downloaded from a remote CDN and saved within your project folder or hosted on a local server. This approach allows you to have full control over the resources.</p>
<h4 id="heading-how-to-host-cdn-resources-locally"><strong>How to host CDN resources locally:</strong></h4>
<p>Hosting locally is straightforward and easy. All you have to do is:</p>
<ul>
<li><p>Access the resource by navigating to the CDN link URL (for example, <a target="_blank" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"><code>https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css</code></a>).</p>
</li>
<li><p>Copy the code found in the URL.</p>
</li>
<li><p>Create a file with the appropriate file extension (.css, .js) within your project folder.</p>
</li>
<li><p>Paste and save.</p>
</li>
<li><p>Reference the file in your HTML document.</p>
</li>
</ul>
<p>If you follow these steps, you should be able to localize the CDN resource and access its styling locally.</p>
<h4 id="heading-advantages-of-a-locally-hosted-cdn"><strong>Advantages of a locally hosted CDN:</strong></h4>
<ol>
<li><p><strong>Full Control over Files:</strong> With resources resident within your project folder/server, you’re in full control of your files as there will be no unexpected outages, changes, or updates that might break your site.</p>
</li>
<li><p><strong>Offline Availability:</strong> Local hosting ensures that your styling resources are always available, especially for users with little or no network. This is perfect for building Progressive Web Applications (PWAs)<strong>.</strong></p>
</li>
<li><p><strong>Customization:</strong> There’s be no need for overrides, as your styling can be modified from within your project files.</p>
</li>
<li><p><strong>Security:</strong> By localizing CDN resources, you reduce the risk of potential third-party attacks on your project to the barest minimum.</p>
</li>
</ol>
<h4 id="heading-disadvantages-of-a-locally-hosted-cdn"><strong>Disadvantages of a locally hosted CDN:</strong></h4>
<ol>
<li><p><strong>No Global Caching:</strong> There is no benefit of global caching when resources are hosted locally. This will result in slower load time for first-time visitors.</p>
</li>
<li><p><strong>Increased Server Load:</strong> With files residing locally, the load on the server increases especially as traffic increases. This approach puts a burden on the server and its capacity has to be considered.</p>
</li>
<li><p><strong>Manual Updates:</strong> While hosting locally gives you control over updates, you’ll need to manually track and apply updates to your stylesheets when necessary. Also, missing security updates could make your site vulnerable.</p>
</li>
<li><p><strong>Regional Performance Impact:</strong> If your server is located in a specific region, users from faraway places may encounter slower load times because the content has to travel greater distances.</p>
</li>
</ol>
<h3 id="heading-hybrid-hosted-cdn"><strong>Hybrid Hosted CDN</strong></h3>
<p>This approach involves the combination of using both the remote link and local hosting of CDN resources. A hybrid approach – which involves using remote CDNs for core libraries and local hosting for custom stylesheets – may strike the perfect balance between performance and control.</p>
<h3 id="heading-best-approach-to-use"><strong>Best Approach to Use</strong></h3>
<p>The decision between remote and local hosting of of your CDN styling resources depends on factors such as project performance needs, user base, and security. Your choice should depend on the suitability of the approach to your project and should elevate the performance levels.</p>
<h4 id="heading-best-use-cases-for-a-remote-cdn"><strong>Best use-cases for a remote CDN:</strong></h4>
<ol>
<li><p><strong>Global User Base:</strong> If your website is to be accessed by a large, globally distributed audience, using the remote option would work best due to its performance and caching advantage.</p>
</li>
<li><p><strong>Fast Integration:</strong> In a situation where you want to develop and deploy a project in the shortest period of time, using the remote CDN link is quick and easy.</p>
</li>
<li><p><strong>Low-Traffic Website:</strong> Small projects such as portfolio sites and blogs are better served using a remote CDN link so as not to put a strain on the server. It also leads to easier implementation.</p>
</li>
</ol>
<h4 id="heading-best-use-cases-for-a-locally-hosted-cdn"><strong>Best use-cases for a locally hosted CDN:</strong></h4>
<ol>
<li><p><strong>High Security Needs:</strong> For applications that require tight security due to the sensitivity of their operations, hosting the CDN resources locally will reduce third-party risks and vulnerabilities.</p>
</li>
<li><p><strong>Offline Applications:</strong> For web applications that work offline, localizing styling resources would be the best option.</p>
</li>
<li><p><strong>Customization Requirements:</strong> If you need to create your tailored styling versions, hosting them locally is the best option.</p>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this guide, you’ve learned what a CDN is, how you can host your CDN, and some of the benefits, drawbacks, and best use-cases for each approach.</p>
<p>Remote CDNs provide speed, convenience and reduced server load, while local hosting offers greater control, security, and customization options.</p>
<p>Ultimately, the best approach depends on your specific use case, audience, and priorities.</p>
<p>You can connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> or <a target="_blank" href="https://x.com/SmoothTee_DC">X</a> for more frontend-related posts and articles.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Design-first vs Logic-first Approach – How Should You Start Your Front-end Projects? ]]>
                </title>
                <description>
                    <![CDATA[ Front-end development is the aspect of web development that involves building user-friendly, dynamic and intuitive interfaces. A front-end developer is primarily concerned about the interface design that the user interacts with and the user’s experie... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/design-first-vs-logic-first-approach/</link>
                <guid isPermaLink="false">66d06c6332b24b6177fc573c</guid>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 29 Aug 2024 12:41:07 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724861983210/118e84bc-0153-4b01-b880-e12fe012b7a5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Front-end development is the aspect of web development that involves building user-friendly, dynamic and intuitive interfaces. A front-end developer is primarily concerned about the interface design that the user interacts with and the user’s experience while using the application.</p>
<p>When starting a project, every front-end developer faces the dilemma of whether to design the interface first or implement the logical part of the application first. The design entails the visual elements displayed on the web application, while the logic refers to the underlying functionalities within the application that dictate its behavior and interaction with users.</p>
<p>In this article, we'll examine both approaches (including their merits and demerits), their best use cases, and how combining them can help achieve set project goals.</p>
<h2 id="heading-design-first-approach"><strong>Design-first Approach</strong></h2>
<p>The design-first approach prioritizes the user interface and user experience aspects of the application. Here, the development process begins with crafting the visual parts such as the navigation, fonts, images, icons, text and background colors, buttons, cards, forms, pop-ups, and so on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724860712401/b0948dc5-8d2e-4f79-95a4-3e2657f467bd.jpeg" alt="computer screen showing visual layout" class="image--center mx-auto" width="4272" height="2848" loading="lazy"></p>
<p>The user experience is also paramount in this approach considering the ease-of-use and accessibility of the application. The main concern of the developer using this approach is how the interface looks to the users. It involves an extensive design of how the elements are laid out and positioned, suitable color scheming and adherence to user interface design principles.</p>
<h3 id="heading-advantages-of-the-design-first-approach"><strong>Advantages of the Design-first Approach</strong></h3>
<p>Adopting the approach of giving utmost attention to the appearance at the early stage of an application’s development can be beneficial in many aspects:</p>
<ul>
<li><p><strong>Clear Visual Reference:</strong> Developers can use the initial design as a visual guide for the final product. This ensures there is less ambiguity about how a product looks for team members, especially designers and stakeholders.</p>
</li>
<li><p><strong>User-Centric Development:</strong> It is a fundamental principle in software development to prioritize users' needs. With a design-first approach, the end user’s experience is at the forefront while starting. Employing this method, it is easier for the developer to tailor the product to be more polished and user-friendly.</p>
</li>
<li><p><strong>Early Feedback:</strong> Feedback is necessary while developing software as it gives room for testing and iterative improvements in the design. Allows for adjustments to be done before investing time in complex logic implementation.</p>
</li>
</ul>
<h3 id="heading-disadvantages-of-the-design-first-approach"><strong>Disadvantages of the Design-first approach</strong></h3>
<p>There are potential challenges associated with the design-first approach such as:</p>
<ul>
<li><p><strong>Potential Rework:</strong> In some scenarios, a significant rework might be needed if the design does not align with technical capabilities. With the logic coming after the design, developers would most likely adjust designs or overhaul an entire section.</p>
</li>
<li><p><strong>Delayed Functionality:</strong> With priorities assigned to design, the core functionalities meant to be integrated into the software may be delayed and lead to a visually pleasing but ‘empty’ application.</p>
</li>
<li><p><strong>Over-emphasis on Aesthetics:</strong> Imagine your dream car with its glamorous bodywork but without an engine to make it function and serve its purpose of being a means of transportation. The same goes for building software with the design-first approach. There is a risk of placing more importance on looks over functionality.</p>
</li>
</ul>
<h3 id="heading-best-use-case-scenarios-for-the-design-first-approach"><strong>Best Use-Case Scenarios for the Design-first Approach</strong></h3>
<p>Having understood what the design-first approach entails, there are scenarios or projects to which this approach is best suited:</p>
<ul>
<li><p><strong>Building Consumer-facing Products:</strong> Customer-facing products are software for the general public rather than business. More emphasis is placed on design and ease of use because they are intended for a broad audience. Factors such as aesthetics, user experience and engagement are pivotal in building these types of applications. Failure to deliver a visually appealing and intuitive interface can make or break the product’s success. Examples of customer-facing products are social media platforms, e-commerce apps, data visualization projects, and so on.</p>
</li>
<li><p><strong>Building Brand-Oriented Projects:</strong> A company’s brand identity encapsulates its values, mission, message and visual elements. As a developer building an application for a company, the brand identity should be intertwined with the aesthetics or user experience. The design-first approach is necessary in such cases as it ensures that every aspect of the product is a true reflection of the brand, aligning perfectly with its identity.</p>
</li>
<li><p><strong>Building content-heavy websites and landing pages:</strong> Websites such as news sites or blogs focus on content layout and content readability which makes design-first perfect for such projects. Landing pages and portfolio sites should also employ this approach as visual impact is paramount.</p>
</li>
<li><p><strong>Prototyping:</strong> In the early stages of product development, a design-first approach can be employed to develop a prototype or Minimum Viable Product (MVP). Prototypes and MVPs are used to test key concepts, impress investors/stakeholders and garner useful user feedback.</p>
</li>
</ul>
<h2 id="heading-logic-first-approach"><strong>Logic-first Approach</strong></h2>
<p>The logic-first approach focuses on the core functionalities, data structure, data flow and architecture before the design aspects. In this method, developers are concerned about the intricacies that involves organizing, updating, retrieving and storing data as regards front-end. Underlying functionalities are extensively worked on before attaching to user interface elements for user interaction, which gives desired results.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724861233496/0854cc54-5777-4212-a0a8-44a256c9d307.jpeg" alt="programmer handling logic" class="image--center mx-auto" width="6000" height="4000" loading="lazy"></p>
<h3 id="heading-advantages-of-the-logic-first-approach"><strong>Advantages of the Logic-first Approach</strong></h3>
<p>Starting an application’s development by focusing on the logical aspects can yield good results such as:</p>
<ul>
<li><p><strong>Strong Architectural Foundation:</strong> By establishing the core logic early, a strong base for the application is formed. This approach aids complex business logic handling and data processing ensuring the application’s base is solid, scalable and maintainable.</p>
</li>
<li><p><strong>Performance Optimization:</strong> The logic-first approach focuses on the systematic fine-tuning of processes such as handling the amount of HTTP requests, API calls, error handling, memory leak prevention, amount of rendering, caching, and so on. With design elements not in the way of the logically-inclined developer, there are no constraints during development.</p>
</li>
<li><p><strong>Early Problem Detection:</strong> By addressing logic first, the identification of technical challenges that may arise later during the application development process is detected earlier. This gives room for necessary adjustments to be done and reduces the risk of a significant rework later.</p>
</li>
</ul>
<h3 id="heading-disadvantages-of-the-logic-first-approach"><strong>Disadvantages of the Logic-first Approach</strong></h3>
<p>While the approach has its merits, it also comes with certain drawbacks that developers should consider. Below, we explore some of the key disadvantages associated with this method.</p>
<ul>
<li><p><strong>Design Compromise:</strong> With logic-first, the design may become a ‘second thought’, leading to an application that is functional but devoid of aesthetic appeal. This might put off users at first interaction because the allure of good user interfaces matters a lot.</p>
</li>
<li><p><strong>User Experience Neglect:</strong> The sole aim of user experience is to satisfy users. An application’s UI might look appealing but fail to create a seamless, efficient and enjoyable impression on the user. Adopting a logic-first approach relegates the user experience to the background and hampers the enjoyability of the app.</p>
</li>
</ul>
<h3 id="heading-best-use-case-scenarios-for-the-logic-first-approach"><strong>Best Use-Case Scenarios for the Logic-first Approach</strong></h3>
<p>Projects that suit this approach emphasize performance, data processing and complex logic. This approach works well with:</p>
<ul>
<li><p><strong>Enterprise Applications:</strong> These are large software built for the corporate world which makes data integrity, security and performance crucial in its development. Starting with logic ensures the application can meet these requirements before designing.</p>
</li>
<li><p><strong>API-Centric Platforms:</strong> With the rise of Application Programming Interface (API) in the technology landscape, it is common to see applications heavily relying on APIs. By extensively consolidating the data flow and logic involved, developers can ensure smooth interactions between the front-end and back-end in the application development process.</p>
</li>
<li><p><strong>Performance-Critical Applications:</strong> The logic-first approach favors building applications where efficiency and speed are critical. Examples of such applications are real-time data processing tools and financial platforms.</p>
</li>
</ul>
<h2 id="heading-hybrid-approach"><strong>Hybrid Approach</strong></h2>
<p>This approach combines the design-first and logic-first approaches used in front-end development. The hybrid approach aims to leverage the strengths of both approaches while lessening their weaknesses.</p>
<p><strong>Key Components of the Hybrid Approach</strong></p>
<p>Certain practices embody the hybrid approach which can be applied in various software development scenarios:</p>
<ul>
<li><p><strong>Parallel Development:</strong> It involves the design and logic teams collaborating concurrently instead of following a sequential process. This offers benefits such as improved efficiency, continuous feedback and swift problem-solving.</p>
</li>
<li><p><strong>Low-Fidelity Prototyping:</strong> Involves creating basic, simplified versions of a product that emphasize key design concepts and core functionalities without showing the detailed final product. It helps in early validation, iterative improvement and risk mitigation.</p>
</li>
<li><p><strong>Component-Based Development:</strong> Involves building reusable components that typically consist of both design and logic. The advantages of using components in developing applications are re-usability, consistency and easy maintenance.</p>
</li>
<li><p><strong>Agile Methodologies:</strong> Using iterative development cycles to alternate between design and logic-focused approaches. It allows for flexibility, room for continuous improvements and balanced focus.</p>
</li>
</ul>
<h3 id="heading-advantages-of-the-hybrid-approach"><strong>Advantages of the Hybrid Approach</strong></h3>
<p>Sharing the focus between the two approaches comes with benefits such as:</p>
<ul>
<li><p><strong>Concurrent Progress:</strong> Working on design and logic together ensures that neither aspect is neglected during the development process. This leads to a product that is both visually appealing and functional.</p>
</li>
<li><p><strong>Improved Communication:</strong> Combining both approaches leads to better collaborations between designers and developers. This ensures designs are feasible and logical aspects seemingly easier to incorporate.</p>
</li>
<li><p><strong>Flexibility:</strong> Rather than waiting for an aspect to be done and reworked later, the hybrid method allows both to develop together and adjustments made in real time.</p>
</li>
</ul>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>The choice between design-first and logic-first approaches depends on individual preference, team capacity, project type, target market or technical requirements.</p>
<p>Developers with a good understanding of each approach’s strengths and weaknesses can make informed decisions that align with their project goals and objectives.</p>
<p>The hybrid approach can be employed to balance out the inadequacies of both of the one-sided approaches. The hybrid approach offers the best of both worlds in the process of crafting both a visually appealing and functionally sound product.</p>
<p>Ultimately, it's up to each individual or team to select the approach that will lead to the best possible product outcome.</p>
<p>If you enjoyed reading this article, you could <a target="_blank" href="https://buymeacoffee.com/timothyolanrewaju">Buy Me a Coffee</a>.</p>
<p>You can also connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> for more insightful posts and articles.</p>
<p>See you in the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Relative Vs Dynamic Routing in React – Different Routing Methods with Examples ]]>
                </title>
                <description>
                    <![CDATA[ Single-Page Applications (SPAs) have been growing in popularity as people become accustomed to better user experiences and improved application responsiveness. This is in part thanks to the introduction of Client-Side Routing (CSR). CSR enables navig... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/relative-vs-dynamic-routing-in-react/</link>
                <guid isPermaLink="false">66ba14e39253a7e34bd1b78d</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 12 Aug 2024 13:57:55 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723295443613/2cf6a928-b2b1-4f71-a6ba-a307b6c13dc9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Single-Page Applications (SPAs) have been growing in popularity as people become accustomed to better user experiences and improved application responsiveness. This is in part thanks to the introduction of Client-Side Routing (CSR).</p>
<p>CSR enables navigation between pages without having to send navigation requests to the server. Instead, it provides instant content updates on navigation. It does this by manipulating the history stack of the browser without making any request for a document to the server.</p>
<p>The benefits of using CSR in building single page applications are:</p>
<ul>
<li><p>It improves user experience as it allows for smoother transitions between pages, resulting in faster interactions.</p>
</li>
<li><p>It increases an application's performance, because loading resources such as JavaScript, CSS, and images is done only once and is then re-used.</p>
</li>
<li><p>It reduces multiple page requests handled by the server, resulting in lower bandwidth usage and quicker response time.</p>
</li>
</ul>
<p>React, the most popular library for building dynamic and complex user interfaces, enables CSR through <code>React Router</code>. React Router is a third-party library that manages navigation and routing in React applications. Big companies such as Shopify, Spotify, Mozilla, and Gumroad (to name just a few) use React Router on their websites.</p>
<p>In this article, we will be taking a deep dive into the types of routing employed in React web applications: <code>Relative</code> and <code>Dynamic</code> routing.</p>
<p>By the end of this article, you will have good knowledge of these routing methods, and you'll be able to differentiate between them. You'll also be able to identify their best use cases and even combine them to achieve desired routing results in your React application.</p>
<h3 id="heading-pre-requisite"><strong>Pre-Requisite</strong></h3>
<p>To fully grasp what we'll discuss in this article, you should have a basic knowledge of React Routing.</p>
<p>If you need to review, you can read my article on <a target="_blank" href="https://www.freecodecamp.org/news/use-react-router-to-build-single-page-applications/">React Router</a>. If you're ready, then let's jump straight into it!</p>
<h3 id="heading-relative-routing">Relative Routing</h3>
<p>Relative routing is a way of defining routes in reference to their parent routes. It enables navigation to different paths or routes within an application based on the current location rather than a specified point which is usually the root of the application.</p>
<p>Relative routing works with relative paths which specify the location of a component in relation to the parent route. We can also say that relative paths are context-sensitive.</p>
<p>Here is a simple example of relative routing using relative paths:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
<span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span></span>;
</code></pre>
<ul>
<li><p>The root route path <code>/</code> renders the <code>Home</code> component.</p>
</li>
<li><p>The <code>&lt;Route path="about" element={&lt;About /&gt;} /&gt;</code> is a relative route that defines the relative path of <code>about</code>. It is relative because it considers the root path <code>/</code> as its parent.</p>
</li>
</ul>
<p>In a nested relative route structure, it works in the same way and still appends to its parent route.</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span></span>}&gt;
<span class="hljs-code">    &lt;Route path="profile" element={&lt;Profile /&gt;} /&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;;</span>
</code></pre>
<ul>
<li><p>The <code>Dashboard</code> route defining the path <code>dashboard</code> still remains a relative route.</p>
</li>
<li><p>The <code>Profile</code> route defining the path <code>profile</code> is nested within the <code>dashboard</code> route which makes it relative to the <code>dashboard</code> path. The full path for <code>Profile</code> will now read <code>/dashboard/profile</code>.</p>
</li>
</ul>
<h3 id="heading-absolute-routing"><strong>Absolute Routing</strong></h3>
<p>Absolute routing is similar to relative routing but with a slight difference. Absolute paths in an application can be distinctly differentiated by the leading slash <code>(/)</code>. The leading slash prefixes the path name and indicates that the path is considered from the root level of the application.</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
<span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span></span>;
</code></pre>
<ul>
<li>The <code>about</code> is an absolute route, defining an absolute <code>about</code> path and directly referencing the root of the application.</li>
</ul>
<p>In an absolute nested route structure, it appears like this:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span></span>}&gt;
<span class="hljs-code">    &lt;Route path="/dashboard/profile" element={&lt;Profile /&gt;} /&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;;</span>
</code></pre>
<ul>
<li>The nested <code>profile</code> route defines the path <code>/dashboard/profile</code> as an absolute path and renders the <code>Profile</code> component when the URL matches <code>/dashboard/profile</code>.</li>
</ul>
<h4 id="heading-differences-between-relative-and-absolute-routing"><strong>Differences between Relative and Absolute Routing</strong></h4>
<ol>
<li><p><strong>Flexibility:</strong> Relative routing is more flexible for nested route structures as relative paths adapt to changes to parent routes automatically. For absolute routing, changes made to parent routes will require an update to all child routes.</p>
</li>
<li><p><strong>Structure:</strong> Relative routes are simpler to manage even in a nested route structure, as child routes append to their parent's route by default. Absolute routing, on the other hand, can become difficult to manage in a complex nested route structure because each path must be explicitly specified.</p>
</li>
<li><p><strong>Clarity:</strong> In a nested route structure, it can be tricky to understand the hierarchical structure in relative routing. It is much easier in absolute routing, as the paths are clear, concise, and direct for non-nested routes.</p>
</li>
</ol>
<h3 id="heading-dynamic-routing">Dynamic Routing</h3>
<p>Applications typically use data, which could be data for users or products and user input. The data can be unique, and it can also change at any point in time, making it dynamic.</p>
<p>Dynamic routing defines routes that can change based on certain parameters using route parameters or URL segments. The parameters added to the route path allow the application to handle routes dynamically and render different elements based on the URL, as you can see in the example below:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span></span>}&gt;
<span class="hljs-code">    &lt;Route path="profile/:id" element={&lt;Profile /&gt;} /&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;;</span>
</code></pre>
<ul>
<li>The <code>Profile</code> route with a dynamic segment <code>:id</code> matching <code>profile/:id</code>. Possible matches for this dynamic path can be <code>profile/123</code> or <code>profile/abc123</code>.</li>
</ul>
<p>The example above shows relative routing with dynamic routing. We can also use absolute routing with dynamic routing:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span></span>} /&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span></span>}&gt;
<span class="hljs-code">    &lt;Route path="/dashboard/profile/:id" element={&lt;Profile /&gt;} /&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;;</span>
</code></pre>
<p><strong>Differences between Static and Dynamic Routing</strong></p>
<ol>
<li><p><strong>Flexibility:</strong> The ability to define a route path according to a parameter makes dynamic routes flexible and responsive to user interaction. Static routes are fixed and do not change.</p>
</li>
<li><p><strong>Complexity:</strong> Dynamic routes often involve dynamic segments like parameters and conditional logic which can be difficult to understand. Static routes are straightforward and non-complex.</p>
</li>
<li><p><strong>Use Case:</strong> Dynamic routes are used for pages that depend on user input or data. Static routes are used for pages that do not change.</p>
</li>
</ol>
<h3 id="heading-how-to-combine-relative-and-dynamic-routing">How to Combine Relative and Dynamic Routing</h3>
<p>If you want to create a more complex or robust navigation system that includes hierarchical and nested route structures, it's best to combine both relative and dynamic routing.</p>
<p>The combination of both routing methods looks like this:</p>
<pre><code class="lang-markdown"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span>&gt;</span></span>
<span class="hljs-code">    &lt;Route path="/categories" element={&lt;Categories /&gt;}&gt;
      &lt;Route path=":categoryId" element={&lt;CategoryDetails /&gt;}&gt;
        &lt;Route path="product/:productId" element={&lt;ProductDetails /&gt;} /&gt;
      &lt;/Route&gt;
    &lt;/Route&gt;
  &lt;/Route&gt;
&lt;/Routes&gt;;</span>
</code></pre>
<ul>
<li><p>This example shows a deeply nested route structure with both relative and dynamic routes.</p>
</li>
<li><p>The full matching path will be <code>/categories/:categoryId/product/:productId</code>.</p>
</li>
</ul>
<p><strong>Benefits of Combining Relative and Dynamic Routing</strong></p>
<ol>
<li><p><strong>Flexibility:</strong> A combination of relative and dynamic routing is best in building a robust navigation structure. This is because it has the flexibility and versatility to define certain routes relatively and other dynamically created routes based on data or user inputs.</p>
</li>
<li><p><strong>Enhanced User Experience:</strong> The combined routing methods will provide users with the best of both methods during interaction leaving them satisfied.</p>
</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this article, we discussed routing in React web applications and learned about the routing methods used in React Router: relative and dynamic routing. They both play crucial roles in client side routing within React applications, and offer different advantages depending on use cases.</p>
<p>Understanding and implementing these routing methods can elevate the user experience and make your React application both maintainable and scalable.</p>
<p>If you enjoyed reading this article, you could <a target="_blank" href="https://buymeacoffee.com/timothyolanrewaju">Buy Me a Coffee</a>.</p>
<p>You can also connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> for more insightful posts and articles.</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use React Router to Build Single Page Applications ]]>
                </title>
                <description>
                    <![CDATA[ Single Page Applications (SPAs) have revolutionized web development. They offer a more dynamic and fluid user experience compared to traditional multi-page applications. Traditional web apps require full-page reloads for almost every click the user m... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-react-router-to-build-single-page-applications/</link>
                <guid isPermaLink="false">66ba29324d935175898a7067</guid>
                
                    <category>
                        <![CDATA[ react router ]]>
                    </category>
                
                    <category>
                        <![CDATA[  Single Page Applications  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 18 Jul 2024 14:42:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/Using-React-Router-to-build-SPAs--Twitter-Post-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Single Page Applications (SPAs) have revolutionized web development. They offer a more dynamic and fluid user experience compared to traditional multi-page applications.</p>
<p>Traditional web apps require full-page reloads for almost every click the user makes. SPAs, on the other hand, load a single HTML page and update the page contents dynamically as users interact with the application. This dynamism mimics the feel of desktop applications and results in better responsive interactions.</p>
<h3 id="heading-before-moving-any-further">Before moving any further:</h3>
<p>To follow along with what I'll discuss in this article, you should have some basic knowledge of React and how to set up a React project. If you already do, let's crack on.</p>
<h2 id="heading-what-are-react-router-and-react-router-dom">What are React Router and React Router DOM?</h2>
<p>React router is a powerful library that manages navigation and routing in React applications. The React Router DOM is used specifically for web applications and has few DOM-specific APIs.</p>
<p>As we dive into the world of React Router DOM, we'll explore its core concepts while demonstrating their implementation in a React application. Our focus will be on building a simple navigation system with links to different components, illustrating how to configure routes, handle route matching, and implement navigation. </p>
<p>By the end of this article, you'll have a solid understanding of how to use React Router DOM to create dynamic and seamless navigation experiences in your single-page applications.</p>
<h2 id="heading-how-to-install-react-router">How to Install React Router</h2>
<p>As I explained above, React-router-DOM is used exclusively for integrating routing functionalities into web applications. So, in order to use it in your React app, you need to install the <code>react-router-dom</code> package by running this command in your React app terminal:</p>
<pre><code class="lang-react">npm install react-router-dom
</code></pre>
<p>After successfully installing it, you can now start routing in your React project. </p>
<h2 id="heading-core-concepts-in-react-router-dom">Core Concepts in React Router DOM</h2>
<h3 id="heading-browserrouter">BrowserRouter</h3>
<p>BrowserRouter a parent component that houses all the route components. All routes that you use in an application must be declared within the <code>BrowserRouter</code>. Most importantly, it stores the current location in the browser's address bar using URLs which comes in handy during navigation.</p>
<p>To use the BrowserRouter, you'll need to import it from the <code>react-router-dom</code> in your App.jsx file.</p>
<pre><code class="lang-react">import { BrowserRouter } from "react-router-dom";

function App() {

  return (
    &lt;BrowserRouter&gt;

    &lt;/BrowserRouter&gt;
  );
}

export default App;
</code></pre>
<p>The <code>BrowserRouter</code> has a <code>basename</code> attribute used to set base URL for all routes in an application. It's important if your app is hosted in a subdirectory on a domain. </p>
<pre><code>&lt;BrowserRouter basename=<span class="hljs-string">"/shop"</span>&gt;

&lt;/BrowserRouter&gt;
</code></pre><p>Adding <code>/shop</code> as a basename will make sure that all route paths are relative to <code>/shop</code>. </p>
<h3 id="heading-routes">Routes</h3>
<p>This component is a direct replacement for <code>switch</code> which was used in the former versions of React Router. It also acts like a parent and renders the first matching child route, which ensures that the correct component is displayed based on the current URL.</p>
<p>To declare routes, import <code>routes</code> from <code>react-router-dom</code> and position it within the <code>BrowserRouter</code> component.</p>
<pre><code class="lang-react">import { BrowserRouter, routes } from "react-router-dom";

function App() {

  return (
    &lt;BrowserRouter&gt;
        &lt;Routes&gt;

        &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

export default App;
</code></pre>
<h3 id="heading-route">Route</h3>
<p><code>Route</code> a child component that consists of two attributes: <strong>path</strong> and <strong>element</strong>. A <strong>path</strong> can be any specified path name while the <strong>element</strong> attribute is the component that should be rendered. A route renders a specific component when the path specified matches a URL.</p>
<p>An application can have as many <code>route</code>s as it needs, and they must all be declared inside the <code>Routes</code> component. Assuming we have a <code>&lt;Home\&gt;</code> and <code>&lt;Pricing\&gt;</code> component, we will have to import the <code>Route</code> component and position it within the <code>Routes</code>.</p>
<pre><code class="lang-react">import { BrowserRouter, Routes, Route } from "react-router-dom";

//ALL COMPONENTS IMPORTS COMES HERE

function App() {

  return (
    &lt;BrowserRouter&gt;
        &lt;Routes&gt;
            &lt;Route path="/" element={&lt;Home/&gt;}/&gt;
                &lt;Route path="pricing" element={&lt;Pricing/&gt;}/&gt;
        &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

export default App;
</code></pre>
<h3 id="heading-undeclared-routes">Undeclared Routes</h3>
<p>There is a way to handle routes that do not exist in your application, just like an Error 404 page. To do this, create another component bearing a Not Found message and the <code>route</code> added.</p>
<p>Set the path name to <code>*</code> and pass the component as the <strong>element.</strong></p>
<pre><code><span class="hljs-keyword">import</span> { BrowserRouter, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-comment">//ALL COMPONENTS IMPORTS COMES HERE</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">BrowserRouter</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"pricing"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Pricing</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"*"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">PageNotFound</span>/&gt;</span>}/&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><h3 id="heading-nested-routes">Nested Routes</h3>
<p>In some cases, routes can have children or sub-routes.</p>
<pre><code><span class="hljs-keyword">import</span> { BrowserRouter, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-comment">//ALL COMPONENTS IMPORTS COMES HERE</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">BrowserRouter</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"pricing"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Pricing</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"categories"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Categories</span>/&gt;</span>}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"male"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Male</span>/&gt;</span>}/&gt;
                        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"female"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Female</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"*"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">PageNotFound</span>/&gt;</span>}/&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>On navigating to the nested elements, the URL on the browser will be reading something like <code>/categories/male</code> and <code>/categories/female</code>.</p>
<h3 id="heading-link">Link</h3>
<p>This acts like an anchor <code>href</code> attribute. It has a <strong>to</strong> attribute which specifies where the <code>Link</code> will take the user after a click. Usually, it is the path to a component's page that is passed to the <strong>to</strong> attribute. </p>
<p>Links are typically put in a Navbar component, so we will put two Links that point to the components path in our already declared Routes.</p>
<pre><code class="lang-react">import { Link } from "react-router-dom";
export default function PageNav() {
  return (
  &lt;&gt;
        &lt;Link to="/"&gt;Home&lt;/Link&gt;
        &lt;Link to="pricing"&gt;Pricing&lt;/Link&gt;
  &lt;/&gt;
  );
}
</code></pre>
<p><strong>NB:</strong> If you are practicing along while reading this article, it is important to note that the <code>PageNav</code> component created here should be situated in your <strong>App.jsx</strong> and specifically just after the opening <code>BrowserRouter</code> tag before the Routes. This is to ensure the <code>PageNav</code> always stays at the top like a navigation menu despite routing through different components.</p>
<pre><code><span class="hljs-keyword">import</span> { BrowserRouter, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-comment">//ALL COMPONENTS IMPORTS COMES HERE</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">BrowserRouter</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PageNav</span>/&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"pricing"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Pricing</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"categories"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Categories</span>/&gt;</span>}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"male"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Male</span>/&gt;</span>}/&gt;
                        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"female"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Female</span>/&gt;</span>}/&gt;
                <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"*"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">PageNotFound</span>/&gt;</span>}/&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><h3 id="heading-navlink">NavLink</h3>
<p>NavLink performs the same function as <code>Link</code> and has a <strong>to</strong> attribute as well. But it's different as it has a class attribute. The class attributes are <code>active</code>, <code>isPending</code>, and <code>isTransitioning</code>. This makes it more versatile than <code>Link</code> and you can use it to conditionally add styles during user interactions.</p>
<pre><code><span class="hljs-keyword">import</span> { NavLink } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</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">PageNav</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">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"pricing"</span>&gt;</span>Pricing<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
  }
</code></pre><h3 id="heading-outlet">Outlet</h3>
<p>Having child elements inside a parent route element means there is a layer of abstraction in rendering the child routes' UI. This is where the <code>Outlet</code> component comes into play. You add it to the parent route – in our example, it would be the <code>Categories</code> component.</p>
<pre><code class="lang-react">import { NavLink, Outlet } from "react-router-dom";
export default function Categories() {
  return (
 &lt;&gt;
          &lt;NavLink to="men"&gt;
            Men
          &lt;/NavLink&gt;
          &lt;NavLink to="women"&gt;
            Women
          &lt;/NavLink&gt;
      &lt;Outlet /&gt;
&lt;/&gt;
  );
}
</code></pre>
<p>This allows for the rendering of the child routes UI in the nested route.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/nested-routes.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Image showing children nested routes in Categories route</em></p>
<h3 id="heading-usenavigate-hook"><code>useNavigate</code> Hook</h3>
<p>This hook returns a function that enables programmatic navigation between routes. </p>
<p>There are several ways to use the navigate function in your application. First, we need to import the <code>useNavigate</code> hook and initialize it as <strong>navigate</strong>.</p>
<pre><code><span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</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">Homepage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <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">h1</span>&gt;</span>This is the Homepage<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>


    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre><p>We can use navigate in the following ways in our application:</p>
<ul>
<li>Attaching it to a button via the <code>onClick</code> prop with the intended path to be navigated to, passed to the navigate function.</li>
</ul>
<pre><code class="lang-react"> &lt;button onClick={() =&gt; navigate("/categories")}&gt;Go to Categories&lt;/button&gt;
</code></pre>
<ul>
<li>Using it with a <code>Link</code> component.</li>
</ul>
<pre><code class="lang-react">&lt;Link to={navigate("/categories")}&gt;Go to Categories&lt;/Link&gt;
</code></pre>
<ul>
<li>Using a number instead of the component path in the <strong>navigate</strong> function. The number should specify the number of navigations backward in the history stack where you would like to go.</li>
</ul>
<pre><code class="lang-react">&lt;Link to={navigate(-1)}&gt;Go one step backwards&lt;/Link&gt;
</code></pre>
<h3 id="heading-useparams-hook"><code>useParams</code> Hook</h3>
<p>Returns an object of the dynamic <code>params</code> gotten from the current URL matched by the Route's path. The parent routes pass all <code>params</code> to their child routes. </p>
<p>The example below shows an <code>OrderPage</code> component that will be rendered for every <code>customer</code> with their unique <code>id</code>. When the URL matches <code>/customer/123</code>, <code>:id</code> will be <code>123</code>.</p>
<pre><code class="lang-react">import { useParams } from "react-router-dom";

function App() {
  const {id} = useParams()
  return (
    &lt;BrowserRouter&gt;
        &lt;Routes&gt;
        &lt;Route path="customer"&gt;
            &lt;Route path=":id" element={&lt;OrderPage/&gt;}/&gt;
           &lt;/Route&gt;
        &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

export default App;
</code></pre>
<h3 id="heading-final-result">Final Result</h3>
<p>At this point, we've fully implemented React Router in our small navigation project. This is what it looks like in full flow:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Untitled-design.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For more detailed information and concepts about React router, you can visit the <a target="_blank" href="https://reactrouter.com/">Official React Router documentation</a> site.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we've explored the concepts and implementation of Client Side Routing (CSR) in a React web application. React Router, through its web-centric library React-Router-DOM, enables CSR, allowing apps to update the URL with a click of a link without making a server request for a new document.</p>
<p>This functionality enhances the user experience by providing faster navigation and a more seamless interaction within the application. By leveraging CSR, developers can build more efficient and responsive single-page applications (SPAs), ultimately improving performance and user satisfaction.</p>
<p>If you enjoyed reading this article, you could <a target="_blank" href="https://buymeacoffee.com/timothyolanrewaju">Buy me a Coffee</a>.</p>
<p>Want to see more of these? Connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a>.</p>
<p>See you on the next one!</p>
<p>Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the useReducer Hook in React ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll take a deep look at the useReducer hook in React. It can look confusing, especially if you are coming across the hook for the first time. This article breaks down the useReducer hook concept into understandable bits with both c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-usereducer-hook/</link>
                <guid isPermaLink="false">66ba292e99186a3f75f2230b</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Fri, 03 May 2024 17:48:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Introduction-to-useReducer-Hook.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll take a deep look at the <code>useReducer</code> hook in React. It can look confusing, especially if you are coming across the hook for the first time. This article breaks down the <code>useReducer</code> hook concept into understandable bits with both code and real-world examples to enable you grasp its functionality.</p>
<p>If you are having a tough time understanding what the <code>useReducer</code> is and how it works, this article is for you. However, a good knowledge of how states works is essential to understand what will be covered in this piece. You can read about React states here: <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/#:~:text=State%20management%20is%20a%20crucial,placed%20in%20your%20applications">State Management In React</a>. You can then join us on the ride to the <code>useReducer</code> land when you are done. If you are already familiar with states, lets go!</p>
<p>Before we go any further, it is important to note that the <code>useState</code> and <code>useReducer</code> hooks are similar in some ways.</p>
<h2 id="heading-how-does-usereducer-compare-to-the-usestate-hook">How Does <code>useReducer</code> Compare to the <code>useState</code> Hook?</h2>
<ul>
<li>They both involve a current state value, and have a function that triggers a state update and an initial state value passed as an argument.</li>
<li>The <code>useReducer</code> is an alternative to the <code>useState</code> hook for managing state in functional components. The <code>useReducer</code> hook is better suited for managing complex state logic while <code>useState</code> is best for simple state changes.</li>
</ul>
<p>When the state logic becomes too complicated or when you need to handle state changes in a more predictable and manageable way, the <code>useReducer</code> hook is your best bet.</p>
<h2 id="heading-what-is-usereducer">What is <code>useReducer</code>?</h2>
<p>A <code>useReducer</code> is a hook in React that allows you add a <code>reducer</code> to your component. It takes in the reducer function and an <code>initialState</code> as arguments. The <code>useReducer</code> also returns an array of the current <code>state</code> and a <code>dispatch</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, initialState);
</code></pre>
<p>Let's familiarize ourselves with what the parameters mean:</p>
<ul>
<li><code>state</code>: represents the current value and is set to the <code>initialState</code> value during the initial render.</li>
<li><code>dispatch</code>: is a function that updates the state value and always triggers a re-render, just like the updater function in <code>useState</code>.</li>
<li><code>reducer</code>: is a function that houses all the logic of how the state gets updated. It takes state and action as arguments and returns the next state.</li>
<li><code>initialState</code>: houses the initial value and can be of any type.</li>
</ul>
<h2 id="heading-deep-dive-into-usereducer">Deep dive into <code>useReducer</code></h2>
<p>Having seen the parts that makes up a useReducer hook, it is time to take a closer look into how it operates.</p>
<p>To use useReducer in your React app, call it at the top level of your component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</code></pre>
<p>We can now use the useReducer hook in our 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> [state, dispatch] = useReducer(reducer, initialState);

  <span class="hljs-keyword">return</span>(
  )
 }
</code></pre>
<p>To see our <code>useReducer</code> hook in action, we will build a very simple counter app that increments by 1 when an increment button is clicked and decrements by 1 when a decrement button is clicked.</p>
<p>Firstly, let us take a closer look at the important  <code>reducer</code> function. This function determines how the state gets updated and contains all the logic through which the next state will be calculated. </p>
<p>Basically, reducers house the logic that is usually placed inside of an event handler when using <code>useState</code>. This makes it easier to read and debug when you are not getting desired results. A quick look at the reducer function can save you the stress.</p>
<p>The reducer function is always declared outside of your component and takes in a current <code>state</code> and <code>action</code> as arguments.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
}
</code></pre>
<p>An <code>action</code> is an object that typically has a <code>type</code> property which identifies a specific action. Actions describe what happens and contains information necessary for the reducer to update the state.</p>
<p>Conditional statements are used to check the action types and perform a specified operation that would return a new state value. Conditional statements like <code>if</code> and <code>switch</code> can be used in reducers.</p>
<h3 id="heading-dispatch-function">Dispatch Function</h3>
<p>This is a function returned by the <code>useReducer</code> hook and is responsible for updating state to a new value. The dispatch function takes the action as its only argument.</p>
<p>We can place the dispatch function inside an event handler function. Remember, actions come with a type property so we have to specify when we call the dispatch function. For our counter app, we have two event handlers that increase and decrease the count.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleIncrement</span>(<span class="hljs-params"></span>) </span>{
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"increment"</span> });
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDecrement</span>(<span class="hljs-params"></span>) </span>{
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"decrement"</span> });
  }
</code></pre>
<p>Now, we'll go back to our reducer function and use the <code>switch</code> condition to evaluate the <code>action.type</code> expression.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"increment"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"decrement"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"Unrecognized command"</span>;
  }
}
</code></pre>
<p>In the above code,</p>
<ul>
<li>The <code>reducer</code> function takes both the state and action as an argument.</li>
<li>We conditionally check for a specific case of the <code>action.type</code> expression string.</li>
<li>If true, a shallow copy of the state is taken by the use of the spread operator and the count value in state is evaluated.</li>
<li>A new state is returned after evaluation has been completed.</li>
<li>The <code>default</code> serves a fallback when no matching case is found.</li>
</ul>
<p>The entire logic of our counter app has been done. We can now return our JSX with the state of <code>count</code> to be displayed on the user interface and the handler functions passed to the <code>onClick</code> event handler for the buttons.</p>
<pre><code class="lang-js"><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">h1</span>&gt;</span>Count:{state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{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">{handleDecrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
</code></pre>
<p>Our counter app is set and the <code>count</code> state will be updated accordingly when the buttons are clicked.</p>
<h2 id="heading-what-happens-behind-the-hood">What Happens Behind the Hood?</h2>
<p>The action of clicking the button triggers a <code>dispatch</code> function that sends an information of <code>type</code> to the reducer function. The dispatching (clicking of the button) causes a re-render of the component. The reducer function conditionally matches the case with the type from the action object and updates the state accordingly after evaluation has taken place.</p>
<p><strong>NOTE</strong>: At dispatch, the reducer function still holds the old value. This means that the dispatch function only updates the state variable for the next render. To check this out, we can log the <code>state</code> and <code>action</code> arguments to the console before the switch statement:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
  <span class="hljs-built_in">console</span>.log(state, action);

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"increment"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"decrement"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"Unrecognized command"</span>;
  }
  }
</code></pre>
<p>After clicking the increment button to increase the count twice, here is what is logged to the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Capture.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>state and action type logged to the console</em></p>
<p>The above image shows that, at the first click, there was an action type of <code>increment</code> made and the initial state value was 0. At the second click, the state value updated to 1, and was displayed as the current count state. I hope you get it now.</p>
<p>Enough of the code gibberish, let's look at a real-world example of the reducer function.</p>
<h2 id="heading-real-world-reducer-example">Real-world Reducer Example</h2>
<p>Picture a dispatcher that works for an online shopping company going to a warehouse to get the goods/items they would later distribute to the people that ordered them.</p>
<p>The dispatcher identifies themself and performs an action of claiming the goods meant for dispatch to the warehouse manager. The manager goes to a box that contains orders shipped and locates the goods meant to be given to the dispatcher. The manager also logs into the inventory system and does the evaluations before handing over the goods to the dispatcher.</p>
<p>This scenario can also be translated as:</p>
<ul>
<li>The dispatcher makes a request for an update or triggers a process like the <code>dispatch</code> function. </li>
<li>The dispatcher performs an action of  'claiming goods' like the dispatch <code>action</code> with a <code>type</code> property.</li>
<li>The warehouse manager does the necessary sorting and updating just like the <code>reducer</code> function.</li>
<li>The box that houses all the goods is updated depending on how many are cleared for dispatch. This acts like the <code>state</code> update.</li>
</ul>
<p>I hope this real-world scenario makes the entire process clearer to you.</p>
<p>Take a look at the full code once again and digest the process.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useReducer } <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">reducer</span>(<span class="hljs-params">state, action</span>) </span>{
  <span class="hljs-built_in">console</span>.log(state, action);
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"increment"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count + <span class="hljs-number">1</span> };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"decrement"</span>:
      <span class="hljs-keyword">return</span> { ...state, <span class="hljs-attr">count</span>: state.count - <span class="hljs-number">1</span> };
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"Unrecognized command"</span>;
  }
}
<span class="hljs-keyword">const</span> initialState = { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> };
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(reducer, initialState);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleIncrement</span>(<span class="hljs-params"></span>) </span>{
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"increment"</span> });
  }
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDecrement</span>(<span class="hljs-params"></span>) </span>{
    dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"decrement"</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">h1</span>&gt;</span>Count:{state.count}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{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">{handleDecrement}</span>&gt;</span>Decrement<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-benefits-of-using-the-usereducer-hook">Benefits of Using the <code>useReducer</code> Hook</h2>
<ul>
<li>Helps centralize state logic.</li>
<li>Makes state transitions predictable.</li>
<li>Suitable for complex state management.</li>
<li>Optimizes performance.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We have covered what the <code>useReducer</code> hook is, how it compares to <code>useState</code> – similarities and differences, the reducer process and the benefits of using <code>useReducer</code>.</p>
<p>If you found this article helpful, you can <a target="_blank" href="https://buymeacoffee.com/timothyolanrewaju">buy me a coffee</a>.</p>
<p>You can also connect with me on <a target="_blank" href="http://linkedin.com/in/timothy-olanrewaju750">LinkedIn</a> .</p>
<p>See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React State vs Refs – Differences and Use Cases ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll delve into a thorough comparison of React state and refs, exploring their suitability for specific scenarios. When faced with the need to store data in your React application, the first question that comes to mind is: "Will the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-state-vs-ref-differences-and-use-cases/</link>
                <guid isPermaLink="false">66ba292c2984e390eea7b654</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 11 Apr 2024 13:07:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/STATE-VS-REF.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll delve into a thorough comparison of React <code>state</code> and <code>refs</code>, exploring their suitability for specific scenarios.</p>
<p>When faced with the need to store data in your React application, the first question that comes to mind is: "Will the data change at some point during the component's lifecycle?" If it won't, a regular <code>const</code> variable is well-suited. </p>
<p>However, if the data will change, then that is where the <code>useState</code> and <code>useRef</code> hooks comes in.</p>
<h2 id="heading-understanding-the-usestate-and-useref-hooks">Understanding the useState and useRef Hooks</h2>
<h3 id="heading-usestate-hook">useState Hook</h3>
<p>The <code>useState</code> hook is designed to manage a component's state, which represents data that can change over time and is important for the component to render. You can add state to your component by importing the <code>useState</code> hook from React.</p>
<pre><code class="lang-react">import { useState } from 'react';
</code></pre>
<p>The <code>useState</code> hook is usually initialized with an initial value and returns an array of a declared state variable and its associated setter function. It looks something like this:</p>
<pre><code class="lang-react">import { useState } from "react";

function App() {
  const [count, setCount] = useState(0); //declared useState hook

  return (
    &lt;&gt;
      &lt;h1&gt;State example&lt;/h1&gt;
      &lt;div&gt;
        &lt;button onClick={() =&gt; setCount((count) =&gt; count + 1)}&gt;
          count is {count}
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}
export default App;
</code></pre>
<p>In the above code,</p>
<ol>
<li>The <code>useState</code> is initialized with a value of zero and returns a <code>count</code> variable and <code>setCount</code> setter function.</li>
<li>The <code>count</code> variable is set dynamically by the <code>setCount</code> setter function that increments the <code>count</code> by 1. </li>
<li>For each click of the button, the <code>App</code> component is re-rendered and the updated value is displayed within the button text.</li>
</ol>
<p>Having a good understanding of React state is important as it is one of the most used concept. You can have a more in-depth read on states here: <a target="_blank" href="https://www.freecodecamp.org/news/react-state-management/">State Management in React</a>.</p>
<h3 id="heading-useref-hook">useRef Hook</h3>
<p>The <code>useRef</code> hook  is used to create refs in React components. A ref is an object with a <code>current</code> property that holds a value. It basically references a DOM element or an instance of a component. We can read and update the value by accessing the current property.</p>
<pre><code class="lang-react">const ref = useRef(initialValue)

ref.current = initialValue
</code></pre>
<p>Here, is a full code snippet of ref in action:</p>
<pre><code class="lang-react">import { useRef } from "react";

function App() {
  let ref = useRef(0); 

  function handleIncrease() {
    ref.current++;
    alert(`You have clicked it ${ref.current} times`);
  }
  return (
    &lt;&gt;
      &lt;h1&gt;Ref example&lt;/h1&gt;
      &lt;div&gt;
        &lt;button onClick={handleIncrease}&gt;Click Me&lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;
</code></pre>
<p>Let's break it down:</p>
<ol>
<li>We imported <code>useRef</code> from React.</li>
<li>In our <code>App</code> component, we declared a <code>ref</code> object with the initial value set to zero.</li>
<li><code>handleIncrease</code> is our handler function that increments the <code>ref.current</code> value by 1 and then alerts the user of the current value.</li>
<li>In our <code>App</code> component's JSX, we have a button with an <code>onClick</code> prop and the <code>handleIncrease</code> handler function passed to it.</li>
</ol>
<p>Having understood how the two hooks work, we'll go ahead to compare and explore when they would be suitable to use.</p>
<h2 id="heading-react-state-vs-ref">React State vs Ref</h2>
<h3 id="heading-render-trigger">Render Trigger</h3>
<p>In React, states always trigger a re-render due to a mechanism known as <code>reconciliation</code> – which updates the user interface based on changes made to the state or props. </p>
<p>Under the hood, React compares the new state to the previous and computes the minimal changes needed to update the user interface that reflects the new state. This process ensures consistency with the changed state or props.</p>
<p>On the flip side, refs do not trigger a re-render when changes are made to it. Refs are not directly linked to the component's rendering cycle. </p>
<p>Therefore, if you want a consistent user interface that reacts to data changes, it is advisable to use states. Refs are better used for managing mutable values without affecting the user interface.</p>
<h3 id="heading-mutability">Mutability</h3>
<p>React state cannot be directly changed once it has been set because the setter function updates of the state variable. By using this approach, React maintains the predictability and stability of the data flow. This also helps in making debugging easier.</p>
<p>Conversely, refs are mutable as you can modify the <code>ref current</code> value outside of the rendering process. Values can be changed at any point unlike states – refs do not have an updater function. </p>
<h3 id="heading-readwrite-operations">Read/Write Operations</h3>
<p>The <code>useState</code> hook setter function allows you to update the state value. For instance:</p>
<pre><code class="lang-react">const [state, setState] = useState(false)
function handleOpposite(){
    setState(!state)
 }
</code></pre>
<p>In this code, we can see that:</p>
<ol>
<li>The initial value is set to a boolean value of <code>false</code>.</li>
<li>The <code>handleOpposite</code> function is negating the boolean value of the <code>state</code>  and the <code>setState</code> houses the updated value of <code>true</code> .</li>
</ol>
<p>In this simple operation,</p>
<ol>
<li>An implicit <strong>read</strong> operation has been done as the initial value had to be accessed before the negation.</li>
<li>A <strong>write</strong> operation occurred when the negation (!) was used on the initial value, which changed the value to the opposite.</li>
</ol>
<p>An explicit <strong>read</strong> operation of state happens when you simply access the state variable directly within a component's JSX. For instance:</p>
<pre><code>&lt;button onClick={<span class="hljs-function">() =&gt;</span> setCount(<span class="hljs-function">(<span class="hljs-params">count</span>) =&gt;</span> count + <span class="hljs-number">1</span>)}&gt;
  count is {count}
 &lt;/button&gt;
</code></pre><p>The <code>{count}</code> is the currently accessed value of the state and would be displayed on the UI accordingly.</p>
<p>On the other hand, accessing or modifying a <code>ref</code>'s current value during rendering can interfere with React's reconciliation process, potentially causing inconsistencies between the virtual DOM and the actual DOM. </p>
<p>In order to ensure predictable behavior and optimal performance in components, it's best to adhere to React's guidelines and avoid either accessing or modifying refs during rendering.</p>
<h3 id="heading-persisting-across-renders">Persisting Across Renders</h3>
<p>Data persistence across renders in React means that data remains consistent and available between different render cycles of a component. When data is persisted, it remains unchanged and accessible after re-rendering. State and Ref both persist data across renders.</p>
<p>Persistence is crucial for maintaining the integrity of the application's state and ensures that components operate as expected. </p>
<h3 id="heading-asynchronous-updates">Asynchronous Updates</h3>
<p>Updates in React state are asynchronous which means that when there is a request for an update, there is a possibility that the updates will not be executed immediately. React might leave some state changes for later while updating other components in one go!</p>
<p>Ref updates are done synchronously where tasks are performed in a sequential manner. Each task waits for the previous one to finish before starting, ensuring that they are executed in a predictable and deterministic manner.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we looked extensively at the hooks — <code>useState</code> and <code>useRef</code> — that handle dynamic data (data that will change) in React applications. </p>
<p>We compared both hooks and at this point, you should be know their similarities, differences, when and where they are best suited.</p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/timothy-olanrewaju750/">LinkedIn</a> for front-end related discussions and posts. See you on the next one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ State Management in React – When and Where to use State ]]>
                </title>
                <description>
                    <![CDATA[ State management is a crucial concept in React, which is one of the most popular JavaScript libraries in the world for building dynamic user interfaces.  Due to its importance in handling data, it is essential know how to manage state, when you need ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-state-management/</link>
                <guid isPermaLink="false">66ba2929c346e93df556afe6</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Timothy Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 05 Feb 2024 21:06:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/rahul-mishra-XXMA-8fBB-g-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>State management is a crucial concept in React, which is one of the most popular JavaScript libraries in the world for building dynamic user interfaces. </p>
<p>Due to its importance in handling data, it is essential know how to manage state, when you need it, and where it can be placed in your applications’ components. </p>
<p>This article dives into the world of React state management, providing a comprehensive guide to help you manage state efficiently. This article is for beginners and intermediate-level of React developers that want to understand how states work.</p>
<h2 id="heading-what-is-state">What is State?</h2>
<p>State can be defined as an object that houses data that changes over time in an application. In other words, state is a dynamic data storage that provides a mechanism for components to manage, keep track of changing data, and trigger re-rendering when it is updated. </p>
<p>Due to modularization in React, state serves as a container that encapsulates relevant data, logic, and behavior within a component. </p>
<p>Now that you know what state means, you can visualize an application even before building it and have an idea of what data would be stored in different states. This brings us to a point I like to call: ‘Thinking In React’. </p>
<p>This coined terminology can be described as the mental picture a React developer has on how to go about building an application in the ‘React way’. Applying knowledge on keeping components pure, passing props from parent to child components, one-way data flow, lifting states up, and many other integral aspects of React.</p>
<h2 id="heading-when-to-use-state">When to Use State</h2>
<p>When building an application, data plays an integral role in what is been displayed or stored. The same applies to building web applications in React, where components display or operate on data — which can be user input, data fetched from APIs, or any other dynamic content. When there is a need to get data that has to be updated inside of a component, we use state.</p>
<p>To understand this better, let’s look at an example of a simple Todo List app that primarily accepts inputted items that would eventually be added to a displayed list. </p>
<p>The item's names will be defined via a text input before being dynamically added to an array of items. </p>
<p>So, we've identified two aspects involving data that would change when triggered. Any update to the data will cause the component to re-render. Those two aspects need the <code>useState</code> hook to update their data and perform the respective logic attached to them.</p>
<pre><code class="lang-react">const [name, setName] = useState(" ")
const [items, setItems] = useState([]);
</code></pre>
<p>Above, is the representation of <code>useState</code> hook functions that allow components to have state variables. As regards to our example of the Todo List app, we initialized our <code>useState</code> function with an empty string (“ ”) for the item names and an empty array (<code>[ ]</code>) for the items. </p>
<p>The <code>useState</code> functions consist of a destructuring assignment that extracts values from an array or properties from an object. In this instance, we are extracting two values returned by the <code>useState</code> functions. </p>
<p><code>name</code> and <code>items</code> hold the current value of the state variable. While <code>setName</code> and <code>setItems</code> are the functions used to update the value of the state variables. </p>
<p>We can add the <code>Header</code>, <code>Nav</code>, <code>ListArea</code> and <code>Footer</code> components to the <code>App</code> component's JSX. Our root component should look like this:</p>
<pre><code class="lang-react">import { useState } from "react";

export default function App() {
      const [items, setItems] = useState([]);
    const [name, setName] = useState(" ")
  return (
    &lt;div&gt;
      &lt;Header /&gt;
      &lt;Nav /&gt;
      &lt;ListArea /&gt;
      &lt;Footer /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>The individual components with their JSX's should look like this:</p>
<pre><code class="lang-react">function Header() {
  return &lt;h2&gt;ToDo List&lt;/h2&gt;;
}

function Nav() {
  return (
    &lt;&gt;
      &lt;input type="text"/&gt;
      &lt;button&gt;Add&lt;/button&gt;
    &lt;/&gt;
  );
}

function ListArea() {
  return (
    &lt;&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/&gt;
  );
}

function Footer() {
  return (
    &lt;&gt;
      &lt;p&gt;You have items in your cart&lt;/p&gt;
    &lt;/&gt;
  );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>How our component's JSXs looks in the browser</em></p>
<p>This is a simple representation of our Todo List. Next, we'll add some logic and make the states come to life. For now, the states reside in the <code>App</code> component.</p>
<h2 id="heading-where-to-use-state">Where to Use State</h2>
<p>When using state, it is important to note that there are two types of states in React development:</p>
<h3 id="heading-global-state">Global State</h3>
<p>These are states that are accessible to every component in the application. It is always declared and located in the root component of your app before the JSX is returned.</p>
<p>A state can be considered as a global state if it is a piece of data that is accessible among multiple components thereby, aiding communication between components in the application.</p>
<h3 id="heading-local-state">Local State</h3>
<p>Local states refers to the internal data maintained by a component. Local states are located within the parent components in an application. They are only needed and can be accessed in the component. </p>
<p>Using local state, components can independently change and handle their data which leads to partitioning within the application.</p>
<p>Looking at our declared states in the Todo List app, we can say that <code>name</code> is a local state and <code>items</code> is a global state.</p>
<p>The reasons are:</p>
<ul>
<li>Two or more components will need access to the <code>items</code> state.</li>
<li>The <code>name</code> state is only needed to input item names into the <code>items</code> list.</li>
</ul>
<p>Here is the structure of our Todo List application with the states positioned according to where they are needed and logic of adding item names to the items list:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</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-comment">//Global state</span>
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

<span class="hljs-comment">//handler function that takes item as a parameter</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleAddItems</span>(<span class="hljs-params">item</span>) </span>{

  <span class="hljs-comment">//setter function that returns a new array with elements from current state with a new item  </span>
    setItems(<span class="hljs-function">(<span class="hljs-params">items</span>) =&gt;</span> [...items, item]);
  }

  <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">Nav</span> <span class="hljs-attr">handleAddItems</span>=<span class="hljs-string">{handleAddItems}</span> /&gt;</span> //passing handleAddItems as props
      <span class="hljs-tag">&lt;<span class="hljs-name">ListArea</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{items}</span> /&gt;</span> //passing items as props
      <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{items}</span> /&gt;</span>    //passing items as props
    <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">h2</span>&gt;</span>ToDo List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Nav</span>(<span class="hljs-params">{ handleAddItems }</span>) </span>{
  <span class="hljs-comment">//Local state function</span>
  <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-comment">//create a handler function that is triggered by Add button</span>
  <span class="hljs-keyword">const</span> handleAddButtonClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//creating a newItem object with name and id properties</span>
    <span class="hljs-keyword">const</span> newItem = { name, <span class="hljs-attr">id</span>: <span class="hljs-built_in">Date</span>.now() };

    <span class="hljs-comment">//passing the newItem object into the handler function as an argument</span>
    handleAddItems(newItem);
    <span class="hljs-comment">// Reset the input field after adding the item</span>
    setName(<span class="hljs-string">""</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">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">{(e)</span> =&gt;</span> setName(e.target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleAddButtonClick}</span>&gt;</span>Add<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-comment">//ListArea component recieving items as props from global state</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ListArea</span>(<span class="hljs-params">{ items }</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">ul</span>&gt;</span>
      //mapping over items array to get individual item as list items
        {items.map((item) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>{item.name}<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="hljs-comment">//Footer component recieving items as props from global state</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Footer</span>(<span class="hljs-params">{ items }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      {items.length !== 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You have {items.length} items in your cart<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You can start adding items to your list<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>The <code>Footer</code> and <code>ListArea</code> components now have access to the items passed down through props. </p>
<p>The act of positioning a state in the root component so it can be accessed globally in a React application is known as "Lifting State Up"- which was what we did with the <code>items</code> state.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Todo List after items have been added to the list</em></p>
<p>Here's a representation of the whole process:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we explored state management in React, when you need them, and where to place state in our applications’ components. </p>
<p>We also broke down how to ‘think in React’, to make our React components interact with each other and give the required output. </p>
<p>React is an interesting user interface library, but can get confusing sometimes if you don’t know the basics. You can now use the knowledge gained in this article to code your projects.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
