<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alberto Cubeddu</title>
    <description>The latest articles on DEV Community by Alberto Cubeddu (@albertocubeddu).</description>
    <link>https://dev.to/albertocubeddu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1283560%2F50b3cde9-6b4a-477e-a1d5-b1e3a780791b.jpg</url>
      <title>DEV Community: Alberto Cubeddu</title>
      <link>https://dev.to/albertocubeddu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/albertocubeddu"/>
    <language>en</language>
    <item>
      <title>AI Talent Acquisition Software</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Fri, 07 Feb 2025 23:09:04 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/ai-talent-acquisition-software-15lj</link>
      <guid>https://dev.to/albertocubeddu/ai-talent-acquisition-software-15lj</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Struggling to Keep Up with Resumes and Calls? Let's Talk AI Engineering in Hiring
&lt;/h2&gt;

&lt;p&gt;Hiring is broken. Well, not broken—just &lt;strong&gt;painfully inefficient&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;CVs pile up. Your phone overheats from too many calls. And your 9-to-5? That’s turned into a &lt;strong&gt;24/7 slog&lt;/strong&gt; of reading resumes, conducting the same first-round questions, and chasing candidates.  &lt;/p&gt;

&lt;p&gt;That’s why &lt;strong&gt;SkillSociety&lt;/strong&gt; exists—to &lt;strong&gt;automate&lt;/strong&gt; the first stages of hiring using AI.&lt;br&gt;&lt;br&gt;
And because this is &lt;strong&gt;dev.to&lt;/strong&gt;, let’s &lt;strong&gt;skip the fluff&lt;/strong&gt; and get straight into &lt;strong&gt;the tech&lt;/strong&gt; behind it.  &lt;/p&gt;




&lt;h2&gt;
  
  
  💡 How We Built an AI Interviewer
&lt;/h2&gt;

&lt;p&gt;SkillSociety is a &lt;strong&gt;fully automated AI-powered interview system&lt;/strong&gt;. Instead of manually screening &lt;strong&gt;dozens or hundreds&lt;/strong&gt; of candidates, our AI handles:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Pre-qualification&lt;/strong&gt; – Filter applicants based on topic-related question based on the &lt;strong&gt;real&lt;/strong&gt; job. Here a Skill Society we do believe that CV are a thing of the past!&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;AI Interviews&lt;/strong&gt; – Candidates speak with an &lt;strong&gt;AI-powered&lt;/strong&gt; interviewer in real-time.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Intelligent Evaluation&lt;/strong&gt; – AI &lt;strong&gt;scores&lt;/strong&gt; responses based on role-specific and personalised criteria.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Insights &amp;amp; Transcripts&lt;/strong&gt; – Structured interview logs for hiring managers to review.  &lt;/p&gt;

&lt;p&gt;Now, let’s break down &lt;strong&gt;the tech stack&lt;/strong&gt; that powers all this.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🏗 The Tech Stack
&lt;/h2&gt;

&lt;p&gt;We designed SkillSociety to be &lt;strong&gt;scalable, real-time, and fully automated&lt;/strong&gt; using a modern web stack:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🏗 &lt;strong&gt;Frontend:&lt;/strong&gt; NextJS (with Server Components)
&lt;/li&gt;
&lt;li&gt;☁ &lt;strong&gt;Backend &amp;amp; Auth:&lt;/strong&gt; Supabase (PostgreSQL + RLS)
&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;AI:&lt;/strong&gt; A combination of: OpenAI, LLama, Deepseek, Sonnet, Whisper, Deepgram, and who know what will be next (LLMs + TTS + ASR)
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Edge Deployments:&lt;/strong&gt; Vercel (Serverless Edge Functions)
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 AI Architecture: LLM + TTS + ASR + (Tooling to cover in another blog post)
&lt;/h2&gt;

&lt;p&gt;AI interviews aren’t just &lt;strong&gt;a simple chat with ChatGPT&lt;/strong&gt;. We needed to build a system that:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understands spoken responses.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluates candidates dynamically.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speaks naturally, with contextual follow-ups.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s how we do it:  &lt;/p&gt;




&lt;h3&gt;
  
  
  📜 Step 1: Large Language Models (LLMs) for Interview Logic
&lt;/h3&gt;

&lt;p&gt;At the heart of our system there are multiple &lt;strong&gt;fine-tuned LLM&lt;/strong&gt;, responsible for:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parsing job descriptions&lt;/strong&gt; to auto-generate &lt;strong&gt;tailored&lt;/strong&gt; interview questions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluating candidate responses&lt;/strong&gt; using structured scoring models.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asking follow-ups&lt;/strong&gt; dynamically based on candidate answers.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;LLM Fine-Tuning:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We &lt;strong&gt;fine-tune&lt;/strong&gt; the model on &lt;strong&gt;real-world&lt;/strong&gt; hiring data to improve domain expertise.
&lt;/li&gt;
&lt;li&gt;Prompt engineering ensures questions &lt;strong&gt;flow naturally&lt;/strong&gt; and are &lt;strong&gt;job-relevant&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;We generate &lt;strong&gt;role-specific prompts&lt;/strong&gt;, adjusting based on industries (tech, finance, healthcare, etc.).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🔊 Step 2: Text-to-Speech (TTS) for Human-Like AI Interviewers
&lt;/h3&gt;

&lt;p&gt;A text-based chatbot isn't enough. We needed AI to &lt;strong&gt;speak&lt;/strong&gt;, making the interview &lt;strong&gt;natural&lt;/strong&gt;.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why We Use TTS:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language support&lt;/strong&gt; for global hiring (We're in Australia and Italy at the moment!).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-like responses&lt;/strong&gt; for a smooth candidate experience.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different tones and accents&lt;/strong&gt; for regional customisation.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;🛠 &lt;strong&gt;Tech Used:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft Azure&lt;/strong&gt; – It's one of the cloud provider we find most attractive from the deployment point of view of new models.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🎙️ Step 3: Automatic Speech Recognition (ASR) for Candidate Responses
&lt;/h3&gt;

&lt;p&gt;Instead of making candidates &lt;strong&gt;type&lt;/strong&gt; answers, we process &lt;strong&gt;spoken responses&lt;/strong&gt; with &lt;strong&gt;ASR&lt;/strong&gt;.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ASR Features:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time speech-to-text transcription&lt;/strong&gt; (low latency).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noise filtering&lt;/strong&gt; (removes background noise).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handles different accents &amp;amp; speech patterns.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyword extraction&lt;/strong&gt; for &lt;strong&gt;automated scoring&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;🛠 &lt;strong&gt;Tech Used:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Whisper ASR (OpenAI)&lt;/strong&gt; – Transcribes speech to text.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deepgram&lt;/strong&gt; – Backup model for multi-accent detection.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Real-Time Interview Pipeline
&lt;/h2&gt;

&lt;p&gt;Here’s how the AI Interview works under the hood:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Candidate starts an AI interview.&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;LLM&lt;/strong&gt; generates &lt;strong&gt;role-specific&lt;/strong&gt; interview questions.
&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;TTS&lt;/strong&gt; converts questions into speech.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Candidate answers in real-time.&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔵 &lt;strong&gt;ASR&lt;/strong&gt; transcribes spoken response.
&lt;/li&gt;
&lt;li&gt;🔵 &lt;strong&gt;LLM&lt;/strong&gt; analyses the answer &amp;amp; generates follow-ups.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI dynamically adjusts interview flow.&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟡 Scores the candidate based on &lt;strong&gt;predefined&lt;/strong&gt; hiring criteria.
&lt;/li&gt;
&lt;li&gt;🟡 Auto-generates &lt;strong&gt;summary reports&lt;/strong&gt; for recruiters.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🛠️ Engineering Challenges
&lt;/h2&gt;

&lt;p&gt;Building an AI-driven interview platform &lt;strong&gt;wasn’t easy&lt;/strong&gt;. Here are a few challenges we tackled:  &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡ Low-Latency AI Processing
&lt;/h3&gt;

&lt;p&gt;Nobody wants &lt;strong&gt;long pauses&lt;/strong&gt; between AI questions and candidate responses.&lt;br&gt;&lt;br&gt;
We optimised performance by:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caching LLM calls&lt;/strong&gt; for common follow-ups.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running ASR inference on the Edge&lt;/strong&gt; to cut down response times.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallelising API requests&lt;/strong&gt; between LLM, TTS, and ASR.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🏎️ &lt;strong&gt;Result:&lt;/strong&gt; &lt;strong&gt;Sub-2s&lt;/strong&gt; response times for dynamic interviews.&lt;br&gt;
&lt;strong&gt;DrawBack:&lt;/strong&gt; We had to create a turn-taking mechanism that is different from anything else in the market. Our use case is Q&amp;amp;A, however with a grain of salt, as the candidate can take some seconds to think about the answer, and you don't want the AI always interrupting or speaking on top of them. &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🏗️ Scalability &amp;amp; High Concurrency
&lt;/h3&gt;

&lt;p&gt;Hundreds of interviews can happen &lt;strong&gt;simultaneously&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
To prevent &lt;strong&gt;bottlenecks&lt;/strong&gt;, we:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployed ASR on a dedicated GPU cluster&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate-limited free-tier users&lt;/strong&gt; to prevent abuse.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🏗️ &lt;strong&gt;Result:&lt;/strong&gt; &lt;strong&gt;No slowdowns, even with high traffic.&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🔒 Data Privacy &amp;amp; Compliance
&lt;/h3&gt;

&lt;p&gt;Recruitment data is &lt;strong&gt;sensitive&lt;/strong&gt;. We built SkillSociety with:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full encryption&lt;/strong&gt; (PostgreSQL + Row-Level Security).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GDPR &amp;amp; ISO 27001 compliance&lt;/strong&gt; for enterprise users.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔐 &lt;strong&gt;Result:&lt;/strong&gt; Secure, enterprise-ready AI hiring.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔥 AI-Powered Hiring: Built for Devs, by Devs
&lt;/h2&gt;

&lt;p&gt;If you’re a hiring manager, recruiter, or startup founder tired of &lt;strong&gt;manual&lt;/strong&gt; screening, it's time to &lt;strong&gt;let AI do the grunt work&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;SkillSociety automates &lt;strong&gt;first-round interviews&lt;/strong&gt; with:  &lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;Real-time, voice-based AI assessments&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Scoring models tailored to each job&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Fully customisable hiring workflows&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.skillsociety.com" rel="noopener noreferrer"&gt;Check out SkillSociety&lt;/a&gt; and see how AI-powered hiring &lt;strong&gt;actually works.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;AI isn’t replacing hiring managers—it’s eliminating the boring parts.&lt;/strong&gt;  &lt;/p&gt;

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

</description>
    </item>
    <item>
      <title>AI at Your Fingertips, Anytime, Anywhere.</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Mon, 05 Aug 2024 03:31:36 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/ai-at-your-fingertips-anytime-anywhere-1iam</link>
      <guid>https://dev.to/albertocubeddu/ai-at-your-fingertips-anytime-anywhere-1iam</guid>
      <description>&lt;p&gt;Introduction video for Extension | OS; The first milestone to bring the mission to fruition! &lt;/p&gt;

&lt;h2&gt;
  
  
  Mission
&lt;/h2&gt;

&lt;p&gt;Imagine a world where everyone can access powerful AI models—LLMs, generative image models, and speech recognition—directly in their web browser. Integrating AI into daily browsing will revolutionise online interactions, offering instant, intelligent assistance tailored to individual needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;I see Artificial Intelligence as the modern equivalent of electricity—essential, transformative, and, yeah, a bit daunting. It's a powerful force that can truly revolutionise our lives, and I reckon everyone should have the chance to experience and benefit from its advancements. By making AI accessible to all, we can unlock its full potential and drive innovation forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/albertocubeddu/extensionos" rel="noopener noreferrer"&gt;Check our Repo on Github&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI/LLMs (ChatGPT, Llama and more) at Your Fingertips, Anytime, Anywhere!</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Mon, 05 Aug 2024 03:04:28 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/aillms-chatgpt-llama-and-more-at-your-fingertips-anytime-anywhere-1797</link>
      <guid>https://dev.to/albertocubeddu/aillms-chatgpt-llama-and-more-at-your-fingertips-anytime-anywhere-1797</guid>
      <description>&lt;p&gt;I want to empower every individual to use artificial intelligence (AI) with a unique user experience and without lock-in from any single provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu30ol4zekyy56y8i0e1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu30ol4zekyy56y8i0e1k.png" alt="Extension | OS Background Logo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Providers: Choose among Groq, OpenAI, Together.ai and your local - host using Ollama!&lt;/li&gt;
&lt;li&gt;Prompt Factory: Effortlessly Tailor Every Prompt to Your Needs with Our Standard Installation.&lt;/li&gt;
&lt;li&gt;Prompt Factory: Choose the Functionality for Every Prompt: From Copy-Pasting to Opening a New Sidebar.
Seamless Integration: Effortlessly access any LLM model directly from your favourite website.&lt;/li&gt;
&lt;li&gt;Secure Storage: Your API key is securely stored in the browser’s local storage, ensuring it never leaves your device.&lt;/li&gt;
&lt;li&gt;[Beta] Mixture of Agents: Experience the innovative Mixture Of Agents feature.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dM1BOxVoebg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshot
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ttw92ge3he0t4wshu51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ttw92ge3he0t4wshu51.png" alt="Extension | OS in action" width="788" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7t6v0qj9nx9lmo58yra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7t6v0qj9nx9lmo58yra.png" alt="Extension | OS" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhixek0iwr7vb584mnbaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhixek0iwr7vb584mnbaq.png" alt="Extension | OS" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh89nzsuymcoz51vexla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh89nzsuymcoz51vexla.png" alt="Extension | OS" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;

&lt;p&gt;Check my github (albertocubeddu) and download it directly from the extensionOS repository! &lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>llm</category>
    </item>
    <item>
      <title>Implementing Conditional Hover States in Nested Divs with React Hooks</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Sun, 04 Aug 2024 01:29:57 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/implementing-conditional-hover-states-in-nested-divs-with-react-hooks-119a</link>
      <guid>https://dev.to/albertocubeddu/implementing-conditional-hover-states-in-nested-divs-with-react-hooks-119a</guid>
      <description>&lt;p&gt;In this article, we’ll simulate an interview scenario. We’ll begin by outlining a specific task and its requirements, and then delve into what a candidate should ideally think and consider during the interview to successfully navigate the situation.&lt;/p&gt;

&lt;h1&gt;
  
  
  The task
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;“Your task is to demonstrate how you would implement a hover effect for nested  &lt;code&gt;div&lt;/code&gt;  elements in a React application. This will involve using React Hooks to manage the conditional behaviour of these elements based on their hover state.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The image provided displays two rectangular panels that represent the transition of a hover effect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; First Panel (“First Header”): Shows the default or initial visual state of the element before any mouse interaction.&lt;/li&gt;
&lt;li&gt; Second Panel (“Second Header”): Depicts the changed appearance of the element when the cursor hovers over it, indicating the hover state has been activated.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Requirements&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  You must use Tailwind CSS.&lt;/li&gt;
&lt;li&gt;  You can omit the arrow, however, pay attention to the underline.&lt;/li&gt;
&lt;li&gt;  Use React Hooks (e.g.,  &lt;code&gt;useState&lt;/code&gt;,  &lt;code&gt;useEffect&lt;/code&gt;) to manage the hover state of the nested  &lt;code&gt;div&lt;/code&gt;  elements.&lt;/li&gt;
&lt;li&gt;  Ensure that the hover state triggers a visual transition between the two states illustrated in the panels.&lt;/li&gt;
&lt;li&gt;  Your solution should accommodate the scenario where hovering over a nested  &lt;code&gt;div&lt;/code&gt;  element triggers its specific hover effect without interfering with the parent or adjacent elements.&lt;/li&gt;
&lt;li&gt;  Your solution should provide a different way to achieve the same result; No code is needed.&lt;/li&gt;
&lt;li&gt;  Ensure you add anything extra you would like to consider if this is a real production application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Start with the analysis
&lt;/h1&gt;

&lt;p&gt;As a candidate, before jumping into technical details, confirm with the interviewer you’ve understood the task, and ensure you’re clarifying the requirements outlining the desired effect upon interaction with the element:&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Based on the task and requirements provided, my understanding is that when the mouse moves beyond the borders of the “rectangular panel,” we are required to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Change the colour of the text for the “Header” and the “Explore”&lt;/li&gt;
&lt;li&gt;  Add an underline on the “Explore”&lt;/li&gt;
&lt;li&gt;  Transition the background from white (#FFF) to black (#000)&lt;/li&gt;
&lt;li&gt;  Ensure no other elements are changed.&lt;/li&gt;
&lt;li&gt;  We can omit the arrow to speed up the development and provide an MVP faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Continue explaining your reasoning
&lt;/h1&gt;

&lt;p&gt;By reading the requirement I understand we must use React (as React hooks are mentioned) and Tailwind. To accomplish the result as requested by using Event Handlers we should start analysing the design, understand the interaction across the elements and finally find a way to communicate the changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Handlers: onMouseEnter and onMouseLeave
&lt;/h2&gt;

&lt;p&gt;Utilising the  &lt;code&gt;onMouseEnter()&lt;/code&gt;  and  &lt;code&gt;onMouseLeave()&lt;/code&gt;, we can detect when the mouse cursor enters or leaves the boundaries of the rectangular element a.k.a “The outer div”.&lt;/p&gt;

&lt;p&gt;Using the return function in those two handlers allows us to send messages downstream to the inner elements, enabling us to apply the hover state where necessary. A straightforward approach would involve implementing a toggle switch that can be turned on or off, signalling the state change to the specific inner elements that need to be adjusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Hooks: useState
&lt;/h2&gt;

&lt;p&gt;Our end objective is to modify the visual state of an element in response to a user event (more specifically a mouseHandler event). By binding the event to the outer div, we can then use the return to understand when the mouse enters/leave the outside area. The last piece of the puzzle is the communication between the EventHandler and the other element(s) inside the component. We can  &lt;code&gt;useState&lt;/code&gt;  specifically registering when the mouse is entering  &lt;code&gt;setIsHovered(true)&lt;/code&gt;  and exiting  &lt;code&gt;setIsHovered(false)&lt;/code&gt;the desired area.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; interface CardProps {  
  headerText: string;  
  paragraphText: string;  
  backgroundColor: string;  
}  

const Card: React.FC&amp;lt;CardProps&amp;gt; = ({  
  headerText,  
  paragraphText,  
  backgroundColor,  
}) =&amp;gt; {  
  const [isHovered, setIsHovered] = useState(false);  

  return (  
    &amp;lt;div  
      id="container"  
      className={containerClass}  
      style={dynamicStyle}  
      onMouseEnter={() =&amp;gt; setIsHovered(true)}  
      onMouseLeave={() =&amp;gt; setIsHovered(false)}  
    &amp;gt; &amp;lt;/div&amp;gt;  
   )  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Reading a state
&lt;/h1&gt;

&lt;p&gt;Now we have our state changing in real-time, if we want to change any of the elements inside the component, we must read the state, and then automatically react will re-render the component based on the condition we specify.&lt;/p&gt;

&lt;p&gt;In our example, we want to apply a conditional hover, and there is nothing simpler than using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span  
  className="flex self-center items-center flex-col"  
  style={{ textDecoration: isHovered ? "underline" : "none" }}  
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Different Alternatives
&lt;/h1&gt;

&lt;p&gt;As mentioned at the beginning the problem can have different solutions; In software engineering, we work with trade-offs where we need to calculate the benefit of one solution against others. In this case, we’ve already a guideline simplifying the decision-making process, however, it’s important to outline some of the different ways.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hover State with CSS — Descendant combinator
&lt;/h2&gt;

&lt;p&gt;Using pure CSS we could avoid the use of hooks and eventHandler, as the :hover  &lt;strong&gt;pseudo-classes&lt;/strong&gt;  and  &lt;strong&gt;descent combinator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;.outer:hover .inner {&lt;br&gt;&lt;br&gt;
    background-color: lightblue; /* Changes when the outer div is hovered */&lt;br&gt;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;Hover over me!  &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I change color when the outer div is hovered over.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Hover State with CSS — Child combinator
&lt;/h2&gt;

&lt;p&gt;Very similar to the solution above, however, we use a more direct specific relationship (parent-child)&lt;/p&gt;

&lt;p&gt;.outer:hover &amp;gt; .inner {&lt;br&gt;&lt;br&gt;
    background-color: lightblue; /* Changes when the outer div is hovered */&lt;br&gt;&lt;br&gt;
  }&lt;/p&gt;

&lt;h1&gt;
  
  
  Production Deployment
&lt;/h1&gt;

&lt;p&gt;I would ensure to provide enough metrics to the product team to understand if the functionality is beneficial to the final user and make data-driven decisions about future enhancements or modifications.&lt;/p&gt;

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

&lt;p&gt;There is always a second way to achieve a result; It’s up to us to understand the context where we are and choose the best solution for the occasion.&lt;/p&gt;

&lt;p&gt;Working solution:  &lt;a href="https://codesandbox.io/p/devbox/still-dream-ywpvwt" rel="noopener noreferrer"&gt;https://codesandbox.io/p/devbox/still-dream-ywpvwt&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscribe Today
&lt;/h2&gt;

&lt;p&gt;If you found this content valuable, consider becoming a  &lt;a href="https://acubeddu87.medium.com/membership" rel="noopener noreferrer"&gt;member&lt;/a&gt;  to access exclusive insights like these.  &lt;a href="https://acubeddu87.medium.com/subscribe" rel="noopener noreferrer"&gt;Subscribe Now&lt;/a&gt;  to be the first to receive updates and emails about my latest work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow me on LinkedIn
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/alberto-cubeddu/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/alberto-cubeddu/&lt;/a&gt;  and suggest other articles you would like to see in this space!&lt;/p&gt;

</description>
      <category>react</category>
      <category>interview</category>
    </item>
    <item>
      <title>useEffect() - What You Need to Know for Acing Tech Interviews!</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Tue, 07 May 2024 08:43:45 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/useeffect-what-you-need-to-know-for-acing-tech-interviews-o51</link>
      <guid>https://dev.to/albertocubeddu/useeffect-what-you-need-to-know-for-acing-tech-interviews-o51</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect()&lt;/code&gt; is one of the React Hooks which, by definition, allow functional components to access state and lifecycle features. They are used to handle side effects, operations that should be separated from the main rendering process. Example of side effects include data fetching, manipulation of the DOM and subscriptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The common rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hooks must be used in React function components.&lt;/li&gt;
&lt;li&gt;Only call them at the top level of a component and avoid conditional use!&lt;/li&gt;
&lt;li&gt;Follow the naming convention ("useHook").&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use in class components (incorrect)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SSComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Incorrect: Hooks cannot be used here!!&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`The count is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Top Level Use (correct)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SSComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Correct: at the top level&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Correct: at the top level&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Used inside conditional (incorrect)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SSComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isLogged&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLogged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// Incorrect: inside a conditional block&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The above will cause issues&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Skill&lt;/span&gt; &lt;span class="nx"&gt;Society&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works - Show me some examples
&lt;/h2&gt;

&lt;p&gt;Let's start with the basic syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Effect&lt;/strong&gt;: F(x) containing the logic. &lt;br&gt;
&lt;strong&gt;Dependency&lt;/strong&gt;: When presents illustrate in an array format which dependencies are watched. If any of the dependencies changes, the useEffect will trigger the F(x). &lt;/p&gt;
&lt;h3&gt;
  
  
  Default Behaviour (execute every time)
&lt;/h3&gt;

&lt;p&gt;It execute every time your component is rendered&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Runs on every render!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Execute once (at component mount)
&lt;/h3&gt;

&lt;p&gt;This emulate the &lt;code&gt;componentDidMount&lt;/code&gt; executing the function as soon as the component is initially rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Runs only on the first render!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;Execute&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;dependency&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;updated&lt;/span&gt;
&lt;span class="s2"&gt;`const [website, setWebsite] = useState('https://skillsociety.com.au');

useEffect(() =&amp;gt; {
  console.log(website); //Run on first render + anytime the dependency value changes!
}, [website]); 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Execute only when a dependency is updated
&lt;/h3&gt;



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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;Dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Visit&lt;/span&gt; &lt;span class="nx"&gt;our&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="nx"&gt;Skill&lt;/span&gt; &lt;span class="nx"&gt;Society&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://skillsociety.com.au&amp;gt;SkillSociety&amp;lt;/a&amp;gt;
      &amp;lt;MyComponent value={2} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function MyComponent({ value }) {
  const isInitialMount = useRef(true);

  useEffect(() =&amp;gt; {
    if (isInitialMount.current) {
      isInitialMount.current = false; // Set to false after the first render
      console.log(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt; &lt;span class="nx"&gt;logic&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;execute&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;rendered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;);
    } else {
      // This code runs only when `value` changes, not on initial mount
      console.log(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="nx"&gt;updated&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, value);
    }
    // This setup ensures the effect is ignored on the initial mount,
    // but runs on subsequent updates to the dependency `[value]`.
  }, [value]); // Dependency array includes only `value`

  return &amp;lt;div&amp;gt;Value is: {value}&amp;lt;/div&amp;gt;;
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  With CleanUp functionality
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevCount&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prevCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Cleanup function to clear the interval&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// Empty dependency array to set up the interval once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The above are just the basic concepts!
&lt;/h3&gt;

&lt;p&gt;Yes, we're only covering the essential concepts you must know for a tech interview. If you want to learn more about advanced dependency management, detailed lifecycle control, optimisation techniques, error handling, and concurrency issues, please DM me on LinkedIn!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/alberto-cubeddu/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>useeffect</category>
      <category>reactjsdevelopment</category>
    </item>
    <item>
      <title>NextJs 14 — App Router and Unit Testing (w/ async pages)</title>
      <dc:creator>Alberto Cubeddu</dc:creator>
      <pubDate>Sat, 17 Feb 2024 21:56:11 +0000</pubDate>
      <link>https://dev.to/albertocubeddu/nextjs-14-app-router-and-unit-testing-w-async-pages-3mml</link>
      <guid>https://dev.to/albertocubeddu/nextjs-14-app-router-and-unit-testing-w-async-pages-3mml</guid>
      <description>&lt;p&gt;Unit testing is pivotal in the Software Development Life Cycle, enabling rapid progress and code refactoring with confidence in the application’s functionality. It minimises production bugs, fosters creative problem-solving, and accelerates coding as the application scales.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2q1hg857d2ki71n93rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2q1hg857d2ki71n93rv.png" alt="NextJs Logo" width="699" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This guide uses NextJs (Version ^14) with the App Router and Jest to set up the unit-testing framework. If you want to skip the step-by-step tutorial, jump to the end of the guide and visit the GitHub link.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Install NextJs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To start, let’s create a new NextJS application using: &lt;code&gt;npx create-next-app@latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mpycv7iapydp4tj46y1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mpycv7iapydp4tj46y1.png" alt="Installing NextJs CLI" width="682" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npx create-next-app@latest&lt;/p&gt;

&lt;p&gt;The command will install a fresh version of NextJS (at the time of writing: 14.0.3) with the configuration specified above.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Install the Jest packages.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To enable the unit testing, we need to install different packages; please run the following command on your terminal inside the root directory of your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftocfiw1berdai80w0b6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftocfiw1berdai80w0b6z.png" alt="Installing JEST" width="311" height="316"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; jest jest-environment-jsdom ts-jest

npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @testing-library/jest-dom @testing-library/react @testing-library/user-event 

npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/jest eslint-plugin-jest-dom eslint-plugin-testing-library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the command, your &lt;code&gt;package.json&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"devDependencies": 
    "@testing-library/jest-dom": "^6.1.4",
    "@testing-library/react": "^14.1.2",
    "@testing-library/user-event": "^14.5.1",
    "@types/jest": "^29.5.10",
    "eslint-plugin-jest-dom": "^5.1.0",
    "eslint-plugin-testing-library": "^6.2.0",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "ts-jest":"^29.1.1"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you’re running the install, the version will most likely be updated; therefore, if they don’t match the above, that’s perfectly ok.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Configure the package.json&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that the packages are ready, we must configure the runner. This involves modifying the &lt;code&gt;package.json&lt;/code&gt; by adding these two lines under the &lt;code&gt;"script"&lt;/code&gt;section&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"test": "jest", 
"test:watch": "jest --watchAll"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command is accessible via &lt;code&gt;npm jest&lt;/code&gt; , and it initiates the manual test run. The second command&lt;code&gt;npm jest:watch&lt;/code&gt; is designed to automatically execute the test upon any changes, triggering a test run each time a test file is saved.&lt;/p&gt;

&lt;p&gt;The script section inside your &lt;code&gt;package.json&lt;/code&gt; should look like the below example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "dev": "next dev",
    "build": "next build",
    "test": "jest", 
    "test:watch": "jest --watchAll",
    "start": "next start",
    "lint": "next lint",
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Configure Jest&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To bootstrap jest, we need to create a file in our root directory named:  &lt;code&gt;jest.config.mjs&lt;/code&gt; and copy/paste the below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import nextJest from 'next/jest.js'


const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: './',
})

// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config = {
  // Add more setup options before each test is run
  setupFilesAfterEnv: ['&amp;lt;rootDir&amp;gt;/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
  preset: 'ts-jest'
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Node.js will treat &lt;code&gt;.cjs&lt;/code&gt; files as CommonJS modules and &lt;code&gt;.mjs&lt;/code&gt; files as ECMAScript modules.&lt;/p&gt;

&lt;p&gt;Create another one called: &lt;code&gt;jest.setup.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@testing-library/jest-dom'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Configure Linting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Open up &lt;code&gt;.eslintrc.json&lt;/code&gt; and add the plugin we’ve installed in the first part of the guide. Your file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "extends": [
    "next/core-web-vitals",
    "plugin:testing-library/react",
    "plugin:jest-dom/recommended"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ESLint statically analyses your code to find problems quickly. It is built into most text editors, and you can run ESLint as part of your continuous integration pipeline. Find issues, Fix problems automatically and give the ability to configure everything!&lt;/p&gt;

&lt;p&gt;After finishing this configuration, we’re ready to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dry Run&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Run the command &lt;code&gt;npm run test&lt;/code&gt; to check everything is installed and working:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6bo0x4xpx1x4pt1ghdz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6bo0x4xpx1x4pt1ghdz.png" alt="npm run test" width="625" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Write your first test&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Using the page provided by the next.js installation, let’s start running the application using: &lt;code&gt;npm run dev&lt;/code&gt; and visiting the URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3ujj38ewb6bfinao3s1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3ujj38ewb6bfinao3s1.png" alt="test run description" width="625" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After visiting the URL, you’ll see the NextJS example page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa04nmlhtagwhcmsveysd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa04nmlhtagwhcmsveysd.png" alt="first view" width="702" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code for the page is located at &lt;code&gt;src/app/page.tsx&lt;/code&gt; and the function is called &lt;code&gt;Home.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Following the naming convention, I usually name the test file after the function. In this example, the file is called: &lt;code&gt;home.test.tsx.&lt;/code&gt; While you can save the file in the same folder as your page resides, I opt to group all my tests in a single directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F467pidwutknptveseifr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F467pidwutknptveseifr.png" alt="file structure" width="243" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Write a simple Jest test&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Open the &lt;code&gt;Home.test.tsx&lt;/code&gt; and start writing your test. To ensure everything works fine, copy-paste this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { render, screen } from '@testing-library/react'
import Home from '@/app/page'
import '@testing-library/jest-dom'

describe('Home', () =&amp;gt; {
    it ('Should Have Learn Text', () =&amp;gt; {
        // Arrange
        render(&amp;lt;Home /&amp;gt;)

        // Act
        const LearnText = screen.getByText('Learn')

        // Assert
        expect(LearnText).toBeInTheDocument()
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where we are looking for the word “Text” in our page, exactly this section below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftt8ipex8uv742qeypd1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftt8ipex8uv742qeypd1d.png" alt="learn" width="258" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;npm run test&lt;/code&gt; or &lt;code&gt;npm run test:watch&lt;/code&gt; it would help if you got a success from your test suite:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3qrga44vtz42gr9v21h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3qrga44vtz42gr9v21h.png" alt="test pass" width="326" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, if you get an error, feel free to contact me, and I’ll help you fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Write an ASYNC Page Jest test&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Thanks to&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/u/f2f82eba5270?source=post_page-----f0ba74b5436b--------------------------------" rel="noopener noreferrer"&gt;Joaquin Lobo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we are expanding this guide to include async testing based on page.&lt;/p&gt;

&lt;p&gt;Following the example on how to fetch data from the &lt;a href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#fetching-data-on-the-server-with-fetch" rel="noopener noreferrer"&gt;NextJS documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function getData() {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos/1')


  if (!res.ok) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data')
  }

  return res.json()
}

export default async function AsyncPage() {
  const data = await getData()

  // Return JSX that properly displays the data
  return (
    &amp;lt;main&amp;gt;
      &amp;lt;h1&amp;gt;Todo Details&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;User ID:&amp;lt;/strong&amp;gt; {data.userId}&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ID:&amp;lt;/strong&amp;gt; {data.id}&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Title:&amp;lt;/strong&amp;gt; {data.title}&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Completed:&amp;lt;/strong&amp;gt; {data.completed ? 'Yes' : 'No'}&amp;lt;/p&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following best-practices for UNIT-Testing, before testing this function we must mock the response of the API call;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global.fetch = jest.fn(() =&amp;gt;
    Promise.resolve({
        ok: true,
        json: () =&amp;gt; Promise.resolve({ userId: 1, id: 1, title: 'Test Todo', completed: false }),
    })
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding the global.fetch before run our test, will allow us to mock the native fetch funcion, available in NextJS 14 by default.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you need to run an&lt;/em&gt; &lt;strong&gt;&lt;em&gt;integration test&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, unfortunately i haven’t found a solution to run the fetch native functionality in JEST, unless i don’t use one of the “replacement” library; However the latter doesn’t ensure your code run as it would with the native function you’re using.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final snippet would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AsyncPage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/app/asyncpage/page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/jest-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AsyncPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should Have User ID and Completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// We are mocking the global.fetch as we're doing unit-test.&lt;/span&gt;
        &lt;span class="c1"&gt;// In case of integration-test, you must include one of the fetch-library to be included.&lt;/span&gt;
        &lt;span class="c1"&gt;// FYI: I wasn't able to include the fetch that next.js loads by default. If you know how to do, open a pull-request.&lt;/span&gt;
        &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test Todo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;AsyncPage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="c1"&gt;// Act&lt;/span&gt;
        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="c1"&gt;// Wait for the data to be fetched and rendered, the AWAIT here is crucial.&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titleElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Test Todo/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="c1"&gt;// Assert&lt;/span&gt;
        &lt;span class="c1"&gt;//////////&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titleElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Now you can use the screen.&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/User ID:/i&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Completed:/i&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This setup kick-starts your journey towards enhancing your application, significantly boosting productivity. It reduces time spent on manual testing and dramatically improves the reliability of your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Subscribe Today&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you found this content valuable, consider becoming a &lt;a href="https://acubeddu87.medium.com/membership" rel="noopener noreferrer"&gt;member&lt;/a&gt; to access exclusive insights like these. &lt;a href="https://acubeddu87.medium.com/subscribe" rel="noopener noreferrer"&gt;Subscribe Now&lt;/a&gt; to be the first to receive updates and emails about my latest work.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Follow me on LinkedIn&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/alberto-cubeddu/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/alberto-cubeddu/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;GitHub Link&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you wish to download a working version of the code, instead of following the guide step-by-step, clone this repository: &lt;a href="https://github.com/albertocubeddu/nextjs-jest-app-router" rel="noopener noreferrer"&gt;https://github.com/albertocubeddu/nextjs-jest-app-router&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sponsored by:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skillsociety.com.au" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nxvkn0sr08txjrt04zs.png" alt="Skill Society Logo" width="715" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>unittest</category>
      <category>react</category>
      <category>jest</category>
    </item>
  </channel>
</rss>
