<?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: Jeffrey Nwankwo</title>
    <description>The latest articles on DEV Community by Jeffrey Nwankwo (@jeffsalive).</description>
    <link>https://dev.to/jeffsalive</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%2F171714%2Fcf2fd326-1598-4e2f-8ec1-d0603c673496.jpeg</url>
      <title>DEV Community: Jeffrey Nwankwo</title>
      <link>https://dev.to/jeffsalive</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeffsalive"/>
    <language>en</language>
    <item>
      <title>A Simple Wrapper for @expo/vector-icons in React Native Projects</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Sat, 15 Feb 2025 01:21:04 +0000</pubDate>
      <link>https://dev.to/jeffsalive/a-simple-wrapper-for-expovector-icons-in-react-native-projects-36b3</link>
      <guid>https://dev.to/jeffsalive/a-simple-wrapper-for-expovector-icons-in-react-native-projects-36b3</guid>
      <description>&lt;p&gt;🖐&lt;/p&gt;

&lt;p&gt;If you work with icons in Expo React Native projects, you're probably familiar with writing:&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;AntDesign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MaterialIcons&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Ionicons&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;@expo/vector-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some context: &lt;a href="https://www.npmjs.com/package/@expo/vector-icons" rel="noopener noreferrer"&gt;@expo/vector-icons&lt;/a&gt; is a compatibility layer around &lt;a href="https://www.npmjs.com/package/react-native-vector-icons" rel="noopener noreferrer"&gt;@oblador/react-native-vector-icons&lt;/a&gt; (the entire community uses this) designed to work with the Expo asset system. If you're using bare React Native without Expo, you're likely using react-native-vector-icons directly and this package isn't for you.&lt;/p&gt;

&lt;p&gt;But for Expo developers, I got tired of switching between documentation to figure out which icon belonged to which set and then importing the set. So I created a simple tiny wrapper:&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;Icon&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-native-unified-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;antdesign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;material-icons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;directions-bike&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ionicons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;airplane&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;One import for all icon sets in @expo/vector-icons&lt;/li&gt;
&lt;li&gt;TypeScript autocomplete for both icon sets and icon names&lt;/li&gt;
&lt;li&gt;NativeWind compatible (&lt;code&gt;className="text-primary"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Supports all 14 icon libraries available in @expo/vector-icons&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-native-unified-icons
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add react-native-unified-icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using with NativeWind
&lt;/h2&gt;

&lt;p&gt;If you're using NativeWind for styling, you can use Tailwind classes:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; 
  &lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;antdesign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;!text-primary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;// Uses your theme's primary color&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Using important modifier&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; 
  &lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;material-icons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favorite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;!text-secondary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;// Forces the secondary color&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why I Made This
&lt;/h2&gt;

&lt;p&gt;I'm currently working on a mobile app with Expo and I found myself constantly checking icon documentation to remember which icon was from which set. It became a small but constant friction. This wrapper simply makes the process more intuitive and provides better TypeScript support.&lt;/p&gt;

&lt;p&gt;The package is tiny and has no additional dependencies beyond @expo/vector-icons (which you're already using in your Expo project).&lt;/p&gt;

&lt;p&gt;Check it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/react-native-unified-icons" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JeffreyChix/react-native-unified-icons#readme" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback and contributions are welcome!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Why Are We Still Learning in 2D When the World is 3D?</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Sat, 30 Nov 2024 23:06:23 +0000</pubDate>
      <link>https://dev.to/jeffsalive/why-are-we-still-learning-in-2d-when-the-world-is-3d-hcd</link>
      <guid>https://dev.to/jeffsalive/why-are-we-still-learning-in-2d-when-the-world-is-3d-hcd</guid>
      <description>&lt;p&gt;🖐 Hello,&lt;/p&gt;

&lt;p&gt;I want to share something exciting that we’re working on, but first, let me paint you a picture.&lt;/p&gt;

&lt;p&gt;Think about how we interact with the world. It’s 3D. We touch, move, build, and explore in three dimensions every day. Now think about how we learn most skills-videos, diagrams, textbooks. It’s all flat. It’s 2D.&lt;/p&gt;

&lt;p&gt;Let’s say you want to learn carpentry. You could watch a YouTube tutorial. Maybe you’ll grab some tools and try to copy what you saw. But then you realize—how do I measure the angles right? How much pressure should I apply when sanding? How do I avoid splitting the wood? These are the kinds of things you only truly understand by doing.&lt;/p&gt;

&lt;p&gt;Or imagine you’re studying to become a mechanic. You watch videos about engines, but the first time you open a hood, you’re overwhelmed. Where’s that bolt they talked about? Which tool fits where? The diagram made it look easy, but in reality, your hands don’t quite know what to do yet.&lt;/p&gt;

&lt;p&gt;The thing is, learning practical skills in a 2D format isn’t how we’re wired. We learn best when we can move, interact, and experiment, when we can fail safely and try again.&lt;/p&gt;

&lt;p&gt;That’s where immersive learning comes in. &lt;/p&gt;

&lt;p&gt;Picture this: instead of watching a video, you step into a virtual workshop. You’re surrounded by tools, machines, and materials. Your instructor is guiding you in real-time, and as you practice, &lt;strong&gt;as you practice&lt;/strong&gt;, you get immediate feedback. It’s as close as you can get to the real thing without the cost, danger, or travel.&lt;/p&gt;

&lt;p&gt;We’re building a platform to make this a reality, focusing on hands-on learning through VR. Whether it’s woodworking, welding, or designing in 3D, you’ll be able to learn by doing, not just watching.&lt;/p&gt;

&lt;p&gt;I'll tell you more...&lt;/p&gt;

&lt;h2&gt;
  
  
  The Game-Changer: VR and AI
&lt;/h2&gt;

&lt;p&gt;Virtual Reality (VR) is one of the most exciting tools we have to revolutionize how we learn. Imagine putting on a headset and stepping into a hyper-realistic workshop. You’re surrounded by virtual tools, materials, and machines, all designed to behave just like their real-world counterparts. With the guidance of AI-powered mentors or live industry professionals, you’re not just watching, you’re doing.&lt;/p&gt;

&lt;p&gt;For example, you’re learning welding. The VR environment lets you practice without risk. Mess up? No big deal. The system will show you where you went wrong and let you try again. The feedback is &lt;strong&gt;immediate and actionable&lt;/strong&gt;, helping you improve faster than traditional methods ever could.&lt;/p&gt;

&lt;p&gt;AI takes it a step further by personalizing your experience. If you’re struggling with a particular step, the system can slow things down, provide tips, or suggest alternate techniques. It’s like having a private tutor who knows exactly what you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Today’s VR Technology: Already Powerful
&lt;/h2&gt;

&lt;p&gt;We’re fortunate that VR technology has advanced significantly in recent years. Headsets like the Meta Quest 3, HTC Vive, and others are now more affordable, accessible, and powerful than ever. They’re no longer clunky gadgets reserved for hardcore gamers; they’re sleek, user-friendly tools that anyone can use. (Though, I still think there's a lot of improvements to make).&lt;/p&gt;

&lt;p&gt;What’s even better? These devices can already handle immersive experiences that replicate real-world environments with incredible detail. Whether it’s the grain of wood in a carpenter’s shop or the heat distortion of a virtual welding torch, VR headsets today are capable of delivering experiences that feel real.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;So, What Exactly Are We Building?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let me introduce you to BlueClod - (&lt;a href="https://www.blueclod.com" rel="noopener noreferrer"&gt;blueclod.com&lt;/a&gt;). Think of it as the ultimate playground for learning practical skills in a way that feels as natural as living in the 3D world around us.&lt;/p&gt;

&lt;p&gt;At its core, BlueClod is an immersive, hands-on learning platform built in virtual reality (VR). But let’s break it down into bite-sized, fun pieces:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Virtual Workshop in Your Pocket
&lt;/h3&gt;

&lt;p&gt;Imagine having access to every tool, every machine, and every material you need for a specific skill—right from your VR headset. With BlueClod, you’re not sitting through a boring lecture or staring at a flat video. You’re actually in a workshop (or a studio, or a garage), holding virtual tools and practicing like you’re really there.&lt;/p&gt;

&lt;p&gt;Want to learn how to fix a car? Step into our virtual auto shop. Dreaming of being a carpenter? Walk into a workshop full of saws, hammers, and drills. No space, no tools, no problem. BlueClod brings them to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Learn By Doing—Not Watching
&lt;/h3&gt;

&lt;p&gt;Remember the times you tried to learn something new by watching a video and felt lost when it came time to do it yourself? BlueClod flips that on its head.&lt;/p&gt;

&lt;p&gt;In our virtual spaces, you’re guided step-by-step through doing. You’re sawing, welding, designing, painting, or fixing. And if you mess up? No sweat. Our system lets you retry, with instant feedback to help you get better. It's like failing forward—fun and stress-free.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Real Mentors, Real Skills
&lt;/h3&gt;

&lt;p&gt;We’re not just throwing you into a virtual world and wishing you luck. BlueClod connects you to real industry experts—artisans, mechanics, and professionals who guide you live or through AI-powered simulations.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’re designing a custom chair. A master carpenter pops in (virtually) to critique your measurements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’re creating an intricate metalwork design, and the system shows you how to perfect your welds in real-time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re never learning alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. For the Dreamers, the Doers, and Everyone in Between
&lt;/h3&gt;

&lt;p&gt;BlueClod isn’t just for professionals or students. It’s for anyone who’s ever said, “I wish I could do that.” Whether you’re picking up a hobby, preparing for a new career, or leveling up your skills, we know we've got something for you.&lt;/p&gt;

&lt;p&gt;It’s also perfect for businesses. Employers can use BlueClod to train teams on equipment and processes without the risk of damage, downtime, or expensive travel. The most exciting part of all this is the AI-driven feedback.&lt;/p&gt;

&lt;p&gt;The plan is not to build a fancy tech toy for the few. BlueClod is designed to be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Affordable&lt;/strong&gt;: Accessible to schools, students, and professionals worldwide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible&lt;/strong&gt;: Compatible with popular VR headsets like Meta Quest and HTC Vive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt;: From woodworking to 3D modeling to industrial training, the possibilities are endless.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;The way we teach and learn hasn’t caught up to the needs of our world. Skilled labor shortages are growing, industries are evolving, and traditional education often leaves students unprepared for real-world challenges.&lt;/p&gt;

&lt;p&gt;By combining VR, AI, and a passion for hands-on learning, we’re aiming to close that gap. We’re making practical education more accessible, more interactive, and frankly, a lot more fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join Us on This Journey
&lt;/h2&gt;

&lt;p&gt;If this vision excites you as much as it excites us, excites me 😃, we’d love your support. Whether you’re someone eager to learn, an industry expert interested in teaching, or an investor who believes in the future of immersive education, there’s a place for you in this journey.&lt;/p&gt;

&lt;p&gt;At the heart of it, BlueClod is about bringing learning to life, helping people do instead of just watch or read. We’re creating virtual spaces where anyone can master hands-on skills, connect with real mentors, and learn in a way that feels as real as the world we live in.&lt;/p&gt;

&lt;p&gt;For me, this isn’t just a project, it’s a passion. I believe that learning should be immersive, exciting, and accessible to everyone, no matter where they are.&lt;/p&gt;

&lt;p&gt;If this resonates with you, I’d love for you to join us on this journey. Whether you’re curious about learning something new, want to share your expertise, or just love the idea of what we’re building, head over to &lt;a href="https://www.blueclod.com/waitlist/form" rel="noopener noreferrer"&gt;BlueClod&lt;/a&gt; and join our waitlist.&lt;/p&gt;

&lt;p&gt;Let’s redefine how we learn—together. &lt;/p&gt;

&lt;p&gt;What’s a skill you’ve always wanted to learn in a hands-on way? &lt;br&gt;
Do you have any thoughts?&lt;/p&gt;

&lt;p&gt;Let me know in the comments!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vr</category>
      <category>software</category>
      <category>unity3d</category>
    </item>
    <item>
      <title>Echo - Anonymous Reporting Platform with Blockchain</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Tue, 13 Aug 2024 11:48:15 +0000</pubDate>
      <link>https://dev.to/jeffsalive/echo-anonymous-reporting-platform-with-blockchain-3dao</link>
      <guid>https://dev.to/jeffsalive/echo-anonymous-reporting-platform-with-blockchain-3dao</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/stellar"&gt;Build Better on Stellar: Smart Contract Challenge &lt;/a&gt;: Build a dApp&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;In today's digital landscape, maintaining anonymity while reporting sensitive issues is more crucial than ever. That's why I created Echo, a cutting-edge decentralized application (dApp) that harnesses blockchain technology to offer a secure, anonymous, and tamper-proof platform for reporting incidents. Whether it's a crime, vandalism, or any other wrongdoing, Echo ensures your voice is heard while safeguarding your identity.&lt;/p&gt;

&lt;p&gt;I believe many unsolved crimes, injustices, and safety concerns remain unresolved because people fear speaking out. If they could share information with complete assurance of anonymity and data integrity, they'd be more inclined to come forward. Echo was designed to meet this need, with reports fully encrypted and securely stored on the blockchain.&lt;/p&gt;

&lt;p&gt;At its core, Echo ensures that all reports and evidence are &lt;strong&gt;encrypted&lt;/strong&gt;, stored using IPFS and Filecoin, and securely uploaded to the blockchain through Stellar's Soroban smart contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here’s a live link to try out Echo: &lt;a href="https://echo-frontend-two.vercel.app" rel="noopener noreferrer"&gt;https://echo-frontend-two.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;I developed Echo using Node.js on the backend to manage the server and interact with smart contracts via the Stellar SDK. The frontend is built with Next.js, TypeScript, Shadcn/ui, and TailwindCSS, focusing solely on rendering the UI.&lt;/p&gt;

&lt;p&gt;Backend Repository: &lt;a href="https://github.com/JeffreyChix/echo-backend" rel="noopener noreferrer"&gt;https://github.com/JeffreyChix/echo-backend&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Frontend Repository: &lt;a href="https://github.com/JeffreyChix/echo-frontend" rel="noopener noreferrer"&gt;https://github.com/JeffreyChix/echo-frontend&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Live Demo: &lt;a href="https://echo-frontend-two.vercel.app" rel="noopener noreferrer"&gt;https://echo-frontend-two.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;The project, &lt;strong&gt;Echo&lt;/strong&gt;, is an anonymous reporting system built on the Stellar blockchain using Soroban smart contracts. It offers a secure, tamper-proof platform for users to report incidents like crimes or misconduct without revealing their identities. The system ensures the integrity and immutability of reports while allowing authorities to access and manage them transparently. To maintain anonymity and ease of use, users can submit reports without needing to connect a wallet, similar to how you wouldn't want to identify yourself or go through authentication when calling 911.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Contract Design:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core functionality of Echo is handled through Soroban smart contracts, which manage the creation, storage, and retrieval of reports. Here's a breakdown of the smart contract architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Report Submission:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a user submits a report with metadata and supporting documents, the report data is encrypted, and a unique key is generated for it. This key is then used to upload the report to the blockchain via smart contracts. It serves as a reference for all future interactions related to the report, such as tracking its status and accessing updates, if the user chooses to monitor it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Storage and Integrity:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The subject, location, and files associated with the report are uploaded to IPFS (InterPlanetary File System) and persisted using Filecoin, a decentralized storage network. The resulting IPFS hashes, along with the report metadata (subject, datetime, description, location), are stored on the blockchain using Soroban smart contracts. This ensures that the data is immutable, verifiable, and accessible only through the unique key.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update Mechanism:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The smart contract also supports the addition of updates to a report. These updates include fields such as status, datetime, and content. Each update is encrypted and stored on the blockchain, linked to the report's unique key. This allows users to track the progress of their report anonymously, ensuring that the information cannot be tampered with.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authority Dashboard:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorities interact with the smart contract through a secure dashboard. They can retrieve reports, view attached evidence, and update the status or provide additional information. All these interactions are recorded on the blockchain, ensuring transparency and accountability.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;My Motivation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Echo was motivated by the urgent need for a platform where individuals can report sensitive incidents without the risk of identification or retaliation. Victims of crimes such as sexual assault, rape, domestic violence, or other misconduct often fear coming forward due to safety concerns or social stigma, and some may not even call 911. Traditional reporting systems can be a deterrent because they typically require personal information.&lt;/p&gt;

&lt;p&gt;Echo was created to address these issues. By using blockchain technology, the platform ensures that individuals can report incidents with complete anonymity, knowing their information will remain secure and unaltered. Soroban smart contracts and IPFS make reports immutable and verifiable by authorities, maintaining the reporter's anonymity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Throughout the development of Echo, I gained significant insights into the complexities of building a decentralized application (dApp) on the Stellar blockchain. Some key learnings include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Balancing Anonymity with Usability:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring complete anonymity while maintaining a user-friendly interface was a significant challenge. I learned how to implement secure, decentralized identity solutions that do not require users to provide personal information or connect a wallet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efficient Data Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handling large files, such as evidence uploads, in a decentralized environment required me to explore and implement IPFS integration. I learned how to optimize data storage and retrieval processes to ensure the system remains scalable and efficient.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Smart Contract Optimization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing and deploying Soroban smart contracts that are efficient, secure, and scalable was a crucial part of my learning journey. I focused on minimizing gas fees and ensuring that the contracts could handle a large number of reports and updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the aspects of Echo that I am most proud of is the &lt;strong&gt;unique key-based tracking system&lt;/strong&gt;. This system allows users to monitor the status of their reports while maintaining their anonymity. By storing updates on the blockchain, I ensure that the information remains tamper-proof, with only the reporter having access through the secret key.&lt;/p&gt;

&lt;p&gt;I am also proud of successfully implementing IPFS for evidence storage. Decentralizing the storage of sensitive files adds an extra layer of security and privacy, ensuring that even platform administrators cannot access or modify the evidence once it is uploaded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges I Faced: From Web2 to Web3 and Rusty Roads
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Diving into Web3:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting Echo was like jumping into the deep end without knowing how to swim. Even though I’ve been coding for five years, I’d never touched blockchain tech or crypto before. When I first heard about Stellar and Soroban, it was like someone threw me into a new world with strange terms like testnets and ledgers. Web3 is a whole different beast from Web2, and I had to start from scratch, learning what all these new concepts meant. The docs were there, but they felt like trying to read a foreign language. It took me a while to get the hang of things, but now I’m really excited to dive deeper and build more dApps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning Rust:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another big challenge was Rust. I had never written any Rust code before, and it felt like learning to drive a stick shift after years of automatic. Rust’s rules and features were pretty foreign to me at first. I had to watch a bunch of tutorials and read up on it to get a handle on how it works. It was tough but also kind of thrilling to figure it out. Rust’s way of doing things made me rethink how I approach coding, and I’m glad I pushed through the learning curve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;String Manipulation Struggles:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the trickiest parts was dealing with string manipulation in Soroban. Since the Rust standard library isn’t available in smart contracts, working with strings became a real hassle. It was like trying to solve a puzzle with missing pieces. I had to get creative and handle some of the string operations outside the smart contracts. It was a frustrating challenge, but it taught me a lot about problem-solving and thinking outside the box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Fetching Issues:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fetching data from the blockchain turned out to be a lot slower than I expected, especially when deployed on Testnet. Even with some optimizations, it was clear that blockchain data retrieval couldn’t compete with the speed of reading from a MongoDB database. To tackle this, I had to get smart on the frontend and use caching along with Incremental Static Regeneration (ISR). This helped improve performance and made the user experience smoother despite the slow data fetching.&lt;/p&gt;

&lt;p&gt;Despite the bumps along the way, I’m more excited than ever about exploring blockchain tech and what’s next in the world of decentralized applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps and Future Improvements:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While Echo is a robust solution, there are several areas where I see potential for growth and improvement:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enhanced User Interface:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I aim to further refine the user interface to make the submission process even more intuitive, especially for individuals who may not be familiar with blockchain technology.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Robust Authentication System&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Currently, the authentication system is basic, using GitHub OAuth just to illustrate the concept of protected routes for the demo. I plan to develop a more comprehensive onboarding process for authorities to securely log in and manage reports. This enhancement will enable more direct and efficient handling of reports while preserving the anonymity of the reporters.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scalability and Performance Optimization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As more users adopt Echo, maintaining the platform's responsiveness and scalability is a priority. Since Web3 and Stellar are new to me, I will continue learning and optimizing the smart contracts and backend infrastructure to handle increased traffic and data storage demands.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Echo represents a significant advancement in anonymous reporting systems, utilizing blockchain technology to offer a secure, transparent, and decentralized platform. Building Echo has been both challenging and rewarding, and I am excited about its potential to help individuals report sensitive issues without fear. As I continue to learn and enhance Echo, my focus remains on ensuring that every voice can be heard, no matter how silent it may seem.&lt;/p&gt;

&lt;p&gt;I welcome any feedback or criticism regarding what might have gone wrong, the feasibility of the project, areas for improvement, and potential integrations.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>stellarchallenge</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Seasoned Software Engineer</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Thu, 10 Aug 2023 08:06:04 +0000</pubDate>
      <link>https://dev.to/jeffsalive/seasoned-software-engineer-3b5d</link>
      <guid>https://dev.to/jeffsalive/seasoned-software-engineer-3b5d</guid>
      <description>&lt;h2&gt;
  
  
  Hello Dev Community! 👋
&lt;/h2&gt;

&lt;p&gt;I'm Jeffrey Nwankwo, a seasoned software engineer with over 5 years of extensive experience in developing, deploying, and managing intricate applications. My expertise lies in JavaScript technologies like React, Next.js, TypeScript, Node.js, and Express.js. However, that's not all – I've also mastered MongoDB and MySQL for robust data management, and I'm well-versed in Azure for cloud-powered solutions.&lt;/p&gt;

&lt;p&gt;🔧 Technologies I Excel In:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Express.js&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💼 Throughout my career, I've deployed applications that cater to the needs of thousands of users. My projects aren't just about coding; they're about creating exceptional user experiences that make an impact.&lt;/p&gt;

&lt;p&gt;🌐 As a passionate advocate of remote work, I'm actively seeking new opportunities to collaborate with diverse teams around the globe.&lt;/p&gt;

&lt;p&gt;💬 My strong communication and leadership skills enable me to seamlessly collaborate and lead projects, ensuring the successful delivery of high-quality solutions.&lt;/p&gt;

&lt;p&gt;🤖 Beyond coding, I have a deep-rooted love for robotics, where innovation meets technology in exciting ways.&lt;/p&gt;

&lt;p&gt;🎬 On weekends, you'll find me immersed in a movie, enjoying my alone time and drawing inspiration from different stories.&lt;/p&gt;

&lt;p&gt;Let's connect and drive innovation together! If you're looking for top-tier expertise in software engineering, I'm your go-to. Feel free to reach out and let's discuss how we can make great things happen. 🚀&lt;/p&gt;

&lt;p&gt;Learn more at &lt;a href="https://www.jeffreynwankwo.com" rel="noopener noreferrer"&gt;https://www.jeffreynwankwo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hire</category>
      <category>softwareengineering</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Effortlessly Create Documentation and Guides with Tango: The Ultimate Time-Saving Tool - It's Free</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Tue, 09 May 2023 20:46:31 +0000</pubDate>
      <link>https://dev.to/jeffsalive/effortlessly-create-documentation-and-guides-with-tango-the-ultimate-time-saving-tool-its-free-34oh</link>
      <guid>https://dev.to/jeffsalive/effortlessly-create-documentation-and-guides-with-tango-the-ultimate-time-saving-tool-its-free-34oh</guid>
      <description>&lt;p&gt;Imagine this scenario - You have finished developing an application and now need to create user documentation for it. As a developer, your primary focus is on writing code and resolving issues. The task of preparing documentation can be intimidating since it requires a significant amount of time and is often tedious. Personally, I would not want to spend hours writing, coding, and capturing screenshots to compile documentation.&lt;/p&gt;

&lt;p&gt;Fortunately, with Tango, you can avoid all of that hassle. Tango is an excellent time-saving tool that developers, product managers, and teams can use to simplify their lives.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Tango takes the pain out of documenting processes by automatically generating how-to guides while you work. Our browser extension and desktop application make it easy for teams to share and scale their knowledge so that everyone feels empowered to learn processes, use new tools, and be their best at work.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By using &lt;a href="https://www.tango.us/" rel="noopener noreferrer"&gt;Tango&lt;/a&gt;, you can easily create guides and document workflows for your team without any additional effort. Tango automatically monitors, processes, and records the steps you take while using your application. It also captures screenshots and generates useful text descriptions, just as you would expect. With Tango, you can effortlessly create comprehensive documentation that your team can use to understand and navigate your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get started 😎
&lt;/h3&gt;

&lt;p&gt;Tango provides two options for usage: a free browser extension and a paid desktop application. However, for web-based tasks, the free extension is typically sufficient. The extension offers several helpful features, such as the ability to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capture workflows within the browser&lt;/li&gt;
&lt;li&gt;edit and redact images&lt;/li&gt;
&lt;li&gt;share and export workflows without any limitations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free browser extension of Tango can be an excellent tool for creating and sharing workflows for web-based tasks.&lt;/p&gt;

&lt;p&gt;To get started, install the free extension&lt;br&gt;
🚧 &lt;a href="https://chrome.google.com/webstore/detail/tango/lggdbpblkekjjbobadliahffoaobaknh" rel="noopener noreferrer"&gt;CLICK TO INSTALL THE FREE EXTENSION&lt;/a&gt;🚧&lt;/p&gt;

&lt;p&gt;After installing the Tango extension, you will be prompted to create a free account. Once you have created an account, you can access your workspace, where all of your workflows are stored. This workspace serves as a central hub for all of your documentation needs and allows you to easily organize, manage, and access your workflows at any time. With Tango, you can streamline your documentation process and keep all of your important information in one convenient location.&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%2Fxiuu2e8yly4bf4jk0khl.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%2Fxiuu2e8yly4bf4jk0khl.png" alt="Tango Workspace" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For better accessibility, pin the extension to your browser tool bar. To start the documenting process, just click the Tango extension icon and hit "CAPTURE WORKFLOW".&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%2Fx46n3n621hxg3tqnnasv.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%2Fx46n3n621hxg3tqnnasv.png" alt="Tango Capture Workflow" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make the Tango extension even more accessible, you can pin it to your browser toolbar. When you are ready to start documenting a workflow, simply click the Tango extension icon and select "CAPTURE WORKFLOW." From there, you can continue with your usual workflow, and Tango will automatically and intelligently document each step you take. This feature allows you to seamlessly integrate documentation into your daily tasks without any extra effort. 🔥🔥🔥&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%2Fpn6pzlhyhj5lmpgu41ny.gif" 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%2Fpn6pzlhyhj5lmpgu41ny.gif" alt="Bad ass gif" width="357" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Who can use Tango?
&lt;/h3&gt;

&lt;p&gt;Anyone can use Tango, regardless of their profession or technical expertise. If you have a workflow or a how-to guide that you need to document and share, Tango is the perfect tool for the job. Instead of spending hours training people on how to use a software or application, you can quickly and easily document the most important steps with Tango in just a few minutes. Tango is particularly popular among developers, content creators, and office workers who need to share a large number of workflows on a regular basis. With Tango, you can save time and effort while ensuring that your workflows are accurately documented and easy to follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I share my workflows?
&lt;/h3&gt;

&lt;p&gt;Tango provides various options for sharing your workflows with others. One option is to share your workflow through a link, which can be accessed by anyone. Alternatively, you can embed your workflow on platforms where your team is already working by using the embed option.&lt;/p&gt;

&lt;p&gt;If you want to collaborate with others, you can invite them to view and make changes to your workflows. Additionally, you can export your workflows as HTML or Markdown files. However, to download your workflows as PDFs, you will need to upgrade to a Pro plan.&lt;/p&gt;

&lt;p&gt;To share your workflow, simply access your workspace, hover over the workflow you want to share, click on the three horizontal dots, and select "Share &amp;amp; Export" from the dropdown options. From there, you can choose the sharing option that best suits your needs.&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%2F1k7n280byyhxw18cxhim.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%2F1k7n280byyhxw18cxhim.png" alt="Tango share and export workflows" width="729" height="454"&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%2F3znsyw1vkp2894zi8sna.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%2F3znsyw1vkp2894zi8sna.png" alt="Tango share and export options" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Tango allows you to customize your privacy settings, giving you control over who can access your workflows. This feature ensures that your sensitive or confidential information remains secure and accessible only to those who need it&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tango pricing
&lt;/h3&gt;

&lt;p&gt;As previously mentioned, the free Tango extension is suitable for web-based tasks, but there may be times when you require additional features available only in the Pro plans. These features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;access to the desktop application&lt;/li&gt;
&lt;li&gt;the ability to blur sensitive information&lt;/li&gt;
&lt;li&gt;remove Tango watermarks, access usage analytics, and automatic PII detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tango offers flexible pricing options to meet your needs, and you can choose the plan that best suits your requirements. You do not have to opt for the most expensive plan; in fact, you can accomplish a lot with any of the available plans. Remember, in most cases, the free extension is all you need, but upgrading to a Pro plan can unlock additional useful features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tango.us/pricing" rel="noopener noreferrer"&gt;See Tango pricing&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Tango saves you time and energy, so you can focus on the things that really matter. Stop pulling your hair out trying to write down every single step, and let Tango do the work for you. Trust me, your future self will thank you for using Tango instead of banging your head against the wall.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tango.us/" rel="noopener noreferrer"&gt;Visit Tango Now!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tango</category>
      <category>documentation</category>
      <category>productivity</category>
      <category>team</category>
    </item>
    <item>
      <title>Join the Discussion: Tell Us About Your Latest Projects 💪💪</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Mon, 08 May 2023 10:54:29 +0000</pubDate>
      <link>https://dev.to/jeffsalive/join-the-discussion-tell-us-about-your-latest-projects-59n3</link>
      <guid>https://dev.to/jeffsalive/join-the-discussion-tell-us-about-your-latest-projects-59n3</guid>
      <description>&lt;p&gt;Hello everyone!&lt;/p&gt;

&lt;p&gt;I hope you're all doing well and had a great weekend! As we start a new week, I'm excited to hear about the cool projects you are working on. Whether it's a personal project or something for work, feel free to share it with us in the comments below.&lt;/p&gt;

&lt;p&gt;We love to see what our community is up to and would be thrilled to check out your projects, so don't hesitate to include links if you have them. Let's spark some conversations and exchange ideas.&lt;/p&gt;

&lt;p&gt;Moreover, if you have any questions related to your projects or anything else, feel free to ask! We're here to support each other and help in any way we can.&lt;/p&gt;

&lt;p&gt;Looking forward to hearing from you all and wishing you a productive week ahead!&lt;/p&gt;

&lt;p&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%2F67h45mf8ddecyje26jv0.gif" 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%2F67h45mf8ddecyje26jv0.gif" alt="Let's go" width="640" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to use Joi Validator in Node + Express Applications. Do it the right way</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Sun, 07 May 2023 17:51:18 +0000</pubDate>
      <link>https://dev.to/jeffsalive/the-right-way-to-use-joi-validator-in-your-nodejs-express-application-147g</link>
      <guid>https://dev.to/jeffsalive/the-right-way-to-use-joi-validator-in-your-nodejs-express-application-147g</guid>
      <description>&lt;p&gt;&lt;a href="https://joi.dev/api/?v=17.9.1" rel="noopener noreferrer"&gt;Joi&lt;/a&gt; is widely considered as the most powerful library for describing schemas and validating data in JavaScript. When it comes to Nodejs applications, especially those built with Express, &lt;a href="https://joi.dev/api/?v=17.9.1" rel="noopener noreferrer"&gt;Joi&lt;/a&gt; offers a simple yet flexible API for defining and validating different types of data like HTTP request parameters, query parameters, request bodies, and more.&lt;/p&gt;

&lt;p&gt;Personally, I've utilized Joi to define validation rules for various data types and effortlessly validate incoming data against them. Joi also offers a diverse range of validation methods that can be customized and combined to cater to specific validation needs. Moreover, it comes with error handling and reporting mechanisms that aid developers in identifying and handling validation errors in a concise and clear manner.&lt;/p&gt;

&lt;p&gt;This isn't a comprehensive article on all things Joi validators. Instead, it focuses on how to utilize it like an expert in a Node + Express application.&lt;/p&gt;

&lt;p&gt;For instance, when dealing with a small application, one can validate the request body in a Node/Express application with Joi by creating a validation schema and utilizing it to validate the request body inside the route handler. All the schemas can be stored in a &lt;code&gt;schemas.ts&lt;/code&gt; file and then imported to the page where request body validation is required. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;joi&lt;/span&gt;&lt;span class="dl"&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Define a validation schema for the request body&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;alphanum&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^[a-zA-Z0-9]{3,30}$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Add a route handler to validate the request body&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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;error&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Valid data, continue with login logic&lt;/span&gt;
    &lt;span class="c1"&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;While it may seem like an easy way to do things, importing validation schemas and validating request bodies inside request handlers is not the best approach, especially when working on medium to large projects with other developers. Over time, this can lead to code that is cluttered and repetitive.&lt;/p&gt;

&lt;p&gt;But don't worry, there is a better approach that I'll show you. To follow along, you can use this starter template I've created. It's a simple setup for a Node + Express + Typescript application that is ready for us to implement the Joi validator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JeffreyChix/joi-starter-template" rel="noopener noreferrer"&gt;Grab the starter template here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After downloading the files, the first step is to run the &lt;code&gt;npm install&lt;/code&gt; command to install all the dependencies. Once that is complete, run the &lt;code&gt;npm run dev&lt;/code&gt; command to start the server. Before proceeding, please verify that everything is working properly. You should see the following message when you open &lt;code&gt;localhost:5000&lt;/code&gt; in your browser:&lt;/p&gt;

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

&lt;p&gt;Now that we have everything set up, we can move on to implementing validation with Joi in our application. To get started, install the Joi npm package by running the command &lt;code&gt;npm install joi&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚧 Our Approach 🚧
&lt;/h3&gt;

&lt;p&gt;Before we start implementing validation with Joi, let's take a moment to discuss the approach we'll be using. We will create a file called &lt;code&gt;schemas.ts&lt;/code&gt; to store all the schemas that our entire application will use. Inside this file, we will export an object where each key/value pair will be the route/path and the corresponding Joi schema to be validated.&lt;/p&gt;

&lt;p&gt;Next, we will create a middleware called &lt;code&gt;SchemaValidator&lt;/code&gt; to validate our request bodies. The &lt;code&gt;SchemaValidator&lt;/code&gt; middleware will accept two arguments. The first argument will be the path (route), and the second argument will be an option to use a custom error message. With the path, we can get the corresponding schema and validate the request body against it.&lt;/p&gt;

&lt;p&gt;Create the &lt;code&gt;schemas.ts&lt;/code&gt; file inside the &lt;code&gt;src&lt;/code&gt; folder and paste this code.&lt;br&gt;
&lt;em&gt;schemas.ts&lt;/em&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;Joi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ObjectSchema&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;joi&lt;/span&gt;&lt;span class="dl"&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;PASSWORD_REGEX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!.@#$%^&amp;amp;*])(?=.{8,})&lt;/span&gt;&lt;span class="dl"&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;authSignup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PASSWORD_REGEX&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authSignin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/auth/signin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authSignin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/auth/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authSignup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectSchema&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Here, we define two validation schemas, &lt;code&gt;authSignup&lt;/code&gt; and &lt;code&gt;authSignin&lt;/code&gt;. These schemas ensure that the input data conforms to specific rules, such as requiring certain fields, ensuring they are of a certain type, and/or conform to specific patterns. The exported object containing the schemas will be used in our &lt;code&gt;SchemaValidator&lt;/code&gt; middleware.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you'd like to learn more about Joi, here's a link to the documentation: &lt;a href="https://joi.dev/api/?v=17.9.1" rel="noopener noreferrer"&gt;https://joi.dev/api/?v=17.9.1&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, create a new folder inside the &lt;code&gt;src&lt;/code&gt; folder and call it &lt;code&gt;middleware&lt;/code&gt;. Inside the &lt;code&gt;middleware&lt;/code&gt; folder, create &lt;code&gt;schemaValidator.ts&lt;/code&gt; file and paste the code below:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;schemas&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;../schemas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ValidationError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;JoiError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ValidationError&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supportedMethods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;put&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;delete&lt;/span&gt;&lt;span class="dl"&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;validationOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;abortEarly&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="na"&gt;allowUnknown&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="na"&gt;stripUnknown&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schemaValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useJoiError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&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;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schemas&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Schema not found for path: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&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="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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&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;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;supportedMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&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="nf"&gt;next&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;error&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validationOptions&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;error&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="na"&gt;customError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid request. Please review request and try again.&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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;joiError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JoiError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ValidationError&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;'"&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;})),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useJoiError&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;joiError&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// validation successful&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;schemaValidator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;SchemaValidator&lt;/code&gt; function takes in a path string and a boolean flag as parameters and returns an Express middleware function.&lt;/p&gt;

&lt;p&gt;The middleware function validates the request body against a predefined schema (the schemas in our schemas.ts file) using the Joi library. If the validation fails, it returns a 422 HTTP status code along with a custom error object that contains either the Joi error or a generic error message, depending on the value of the &lt;code&gt;useJoiError&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;If the validation succeeds, it sets the request body to the validated value and calls the next() function to pass control to the next middleware. Pretty simple. &lt;/p&gt;

&lt;p&gt;Now that we have set up our approach, we can use the SchemaValidator middleware in our route definitions. For example, here's how we can use it to validate the auth routes.&lt;/p&gt;

&lt;p&gt;First, create a new folder called &lt;code&gt;auth&lt;/code&gt; inside the &lt;code&gt;routes&lt;/code&gt; folder. Inside the &lt;code&gt;auth&lt;/code&gt; folder, create an &lt;code&gt;index.ts&lt;/code&gt; file where we will define the two authentication routes: the &lt;code&gt;signup&lt;/code&gt; and &lt;code&gt;signin&lt;/code&gt; routes.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Then import the auth routes in the main &lt;code&gt;routes/index.ts&lt;/code&gt; file.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;authRoutes&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;./auth&lt;/span&gt;&lt;span class="dl"&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Dev Community!&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="c1"&gt;//? Import other routes here&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/v1/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//* eg: router.use("/api/v1/user", userRoutes);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Back to the auth routes file, uur route handler will require some data from the user to process, this is where we first validate the user input before it gets to our handler.&lt;/p&gt;

&lt;p&gt;To use the &lt;code&gt;SchemaValidator&lt;/code&gt; middleware, import it into the file, and apply it as a middleware function just before the route handlers for the "signin" and "signup" routes. Use the &lt;code&gt;schemaValidator&lt;/code&gt; function and pass the path associated with the correct schema, similar to what was done in the schemas.ts file.&lt;/p&gt;

&lt;p&gt;The updated code will look something like this:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;schemaValidator&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;../../middleware/schemaValidator&lt;/span&gt;&lt;span class="dl"&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;schemaValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/auth/signin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You've successfully logged in ✔&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;schemaValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/auth/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sign up complete ✔&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Now that we have defined our authentication routes, we can test them using Postman. Start your dev server by running &lt;code&gt;npm run dev&lt;/code&gt;. To test the &lt;code&gt;signup&lt;/code&gt; route, enter &lt;code&gt;localhost:5000/api/v1/auth/signup&lt;/code&gt; in Postman and set the request method to &lt;code&gt;POST&lt;/code&gt; and the request body type to &lt;code&gt;raw/JSON&lt;/code&gt;. If we make the request without entering anything, we will get an error response like this:&lt;/p&gt;

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

&lt;p&gt;And if we enter all the required fields correctly, we should receive a response with the message "Sign up complete ✔".&lt;/p&gt;

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

&lt;p&gt;You can also test the &lt;code&gt;signin&lt;/code&gt; route and experiment with different payloads to see the different error messages that can be generated.&lt;/p&gt;

&lt;p&gt;With this implementation, we can easily create more routes and schemas in our application without worrying about validating each schema. All we need to do is create the schema in the schemas.ts file and apply the SchemaValidator middleware wherever we want to validate the schema. This approach helps to keep our code organized and avoids code repetition.&lt;/p&gt;

&lt;p&gt;How exciting right?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;It is important to follow standard conventions and organize your application logic in the service and controller folders. In this example, however, we did not follow that convention because it was not the focus of this tutorial.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The approach we discussed here makes the process of validating data in our Node.js applications easier and more efficient. By using a centralized schema validation approach, we avoid repetitive code and ensure that our code remains clean and easy to understand. Additionally, this approach makes it easy for other developers to pick up our code and understand it.&lt;/p&gt;

&lt;p&gt;It is worth noting that this approach can also be applied to other validation libraries in Node.js, such as Zod. Overall, this approach can save us a lot of time and make our codebase more maintainable. Happy coding, and feel free to leave any thoughts or questions in the comments section.&lt;/p&gt;

&lt;p&gt;That's the end of the guide! You can access the complete code by visiting &lt;a href="https://github.com/JeffreyChix/joi-node-schema-validation" rel="noopener noreferrer"&gt;https://github.com/JeffreyChix/joi-node-schema-validation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more content like this, follow me on Twitter &lt;a href="https://twitter.com/JeffreySunny1" rel="noopener noreferrer"&gt;@JeffreySunny1&lt;/a&gt;. My DM is open.&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>joi</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Psychology of Success in Tech is a Complex Beast. What does it Take to Succeed in the Tech Industry?</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Thu, 04 May 2023 04:29:39 +0000</pubDate>
      <link>https://dev.to/jeffsalive/the-psychology-of-success-in-tech-is-a-complex-beast-what-does-it-take-to-succeed-in-the-tech-industry-gn0</link>
      <guid>https://dev.to/jeffsalive/the-psychology-of-success-in-tech-is-a-complex-beast-what-does-it-take-to-succeed-in-the-tech-industry-gn0</guid>
      <description>&lt;p&gt;Well, well, well, look who we have here, a tech industry newbie feeling all hopeful and super pumped about their career. You're already daydreaming about your future success, just like every other human being on this planet. But fast forward a few years and reality hits you like a ton of bricks.&lt;/p&gt;

&lt;p&gt;You've been putting in the hard work for one, two, three years now, but there's nothing to show for it. And to make matters worse, every time you hop on social media, you're bombarded with posts that crush your spirit and make you feel like you're not doing enough. It's like Twitter and LinkedIn have a personal vendetta against you.&lt;/p&gt;

&lt;p&gt;LinkedIn boasts: "&lt;em&gt;I'm happy to announce that I'm now the TechnoKing 2 of Tesla and SpaceX&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Twitter chirps: "&lt;em&gt;Just landed a new gig, making $10,000 every two weeks. Tech is the best!&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;And let's not forget Instagram, the platform that screams: "&lt;em&gt;Pictures of strangers who started a year ago, and are now vacationing in Bali while making millions from their tech startups&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Meanwhile, you're struggling to even afford a new keyboard for your laptop. Wallet? Empty. MacBook? Nope. Two 32-inch monitors on your adjustable electric table? Dream on. And don't even get started on that Logitech mouse and mechanical keyboard.&lt;/p&gt;

&lt;p&gt;I mean, come on, three years down the line and you can't even replace your keyboard? That's not just a bad situation, that's downright tragic. &lt;/p&gt;

&lt;p&gt;Even the baby is laughing at ya 🤣.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The second perspective:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You're not exactly a tech industry newbie. You've been in the game for a while, you've got some professional experience under your belt. You can at least afford to replace your keyboard, but things still aren't where you want them to be.&lt;/p&gt;

&lt;p&gt;Let's face it, you're not exactly killing it in the tech world. You're stuck doing gigs at lower rates than you deserve, because let's be real, sometimes you just have to take what you can get in order to pay the bills. It's not exactly the glamorous life that you see on social media.&lt;/p&gt;

&lt;p&gt;You don't have three MacBook M1 Max on your desk, and a vacation to Bali is definitely not in your near future. But hey, we're all in the same boat, right? We're just trying to make it in this crazy tech world, one day at a time.&lt;/p&gt;

&lt;p&gt;I want you to know that I'm not some tech influencer with a massive following, nor do I have an abundance of resources at my disposal. I'm just a regular person who has been working in the tech industry for a while, and I've seen some patterns that I think are worth sharing.&lt;/p&gt;

&lt;p&gt;So if you're feeling like you're not quite where you want to be in your tech career, don't worry, you're not alone. We're all just trying to figure it out one day at a time. And hopefully, with some of the tips and insights I'll be sharing, we can all get a little bit closer to our goals.&lt;/p&gt;

&lt;p&gt;Time to pick ourselves up, dust off those insecurities, and get back to grinding. Because in the tech industry, there's no time to waste.&lt;/p&gt;

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

&lt;p&gt;Let me tell you a little story about myself. Back in 2017, I wrote my first line of code and it was like a religious experience. I'm pretty sure that GOD Himself blessed me with this love for technology from a very young age. But you know what they say, with great love comes great responsibility, and that's why I knew I had to develop this gift.&lt;/p&gt;

&lt;p&gt;I started out with some beginner-friendly projects and gave it my all. But when it came time to land my first job, I quickly realized that I was a tiny fish in a big ocean of tech masters. I mean, have you seen my first resume? It was a joke. It probably would have been more impressive if it just said "&lt;em&gt;can turn on a computer and type without looking at the keyboard.&lt;/em&gt;"&lt;/p&gt;

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

&lt;p&gt;Back then, I wouldn't even hire myself with a fake name and a wig, but hey, I was desperate to get my foot in the door. And let me tell you, it's not a walk in the park, it's more like a marathon through a minefield.&lt;/p&gt;

&lt;p&gt;But I didn't let that discourage me. I kept pushing and learning, and eventually, I landed my first job as a junior developer.&lt;/p&gt;

&lt;p&gt;Fast forward to today, and while I'm not exactly living the tech mogul dream just yet, I'm at least closer than I was before. To be honest, I'm still closer to understanding quantum physics than I am to becoming the next Elon Musk.&lt;/p&gt;

&lt;p&gt;That being said, I've done my fair share of digging into the psychology of success in the tech industry. I've asked myself the tough questions like:&lt;/p&gt;

&lt;p&gt;👉 What's my role in all of this?&lt;br&gt;
👉 What's the industry's role?&lt;br&gt;
👉 Are my skills worth their weight in RAM?&lt;br&gt;
👉 Why is that one guy crushing it after only two years while I'm still struggling after five?&lt;br&gt;
👉 What am I doing wrong and what are they doing right?&lt;br&gt;
👉 And of course, what's the magic potion?&lt;/p&gt;

&lt;p&gt;If you're anything like me, these questions have probably popped into your head a few (hundred) times too.&lt;/p&gt;

&lt;p&gt;The answer to these questions is lightly hidden in the problems. Trust me, from my personal experiences and observations, there are actually reasons why most people don't succeed in tech. It's not like the universe is conspiring against you, but let's take a closer look, shall we?&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Lack of commitment
&lt;/h3&gt;

&lt;p&gt;If you're not a little kid, you probably know that the real world is one tough cookie. And if you think success comes easy, think again! Even selling drugs takes effort, you know? (Not that I would know, of course... ahem) And don't even get me started on the tech industry! It's a &lt;em&gt;dog-eat-dog&lt;/em&gt; world out there, and if you can't handle the heat, you'll get left behind like yesterday's garbage.&lt;/p&gt;

&lt;p&gt;I mean, come on! You think you can just waltz into the tech industry with big dreams and high hopes, and everything will magically fall into place? HA! That's like trying to build a house of cards in a windstorm. Learning new technologies is hard work, my friend. It's like trying to decipher hieroglyphics while riding a unicycle on a tightrope. And let's not forget about turning your ideas into actual products! That's like trying to turn water into wine, except without any divine intervention.&lt;/p&gt;

&lt;p&gt;The thing is, if you want to succeed in tech, you've got to commit. I'm not talking about half-assed commitment, either. I'm talking about &lt;strong&gt;full-on&lt;/strong&gt;, &lt;strong&gt;balls-to-the-wall&lt;/strong&gt;, &lt;strong&gt;all-in&lt;/strong&gt;, &lt;strong&gt;no-holds-barred&lt;/strong&gt; commitment. You've got to be willing to put in the time and effort to make progress. It doesn't matter if you've been in the industry for five years or five minutes. If you're not committed, you're going to get left in the dust faster than a cheetah on roller skates. &lt;/p&gt;

&lt;p&gt;At the end of the day, the difference between the guy who's killing it and the guy who's struggling is &lt;strong&gt;COMMITMENT&lt;/strong&gt;🔥 .&lt;/p&gt;

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

&lt;h3&gt;
  
  
  2. Poor work ethic
&lt;/h3&gt;

&lt;p&gt;It's no secret that the world has gone tech-crazy in the last few years. Everyone and their grandma is trying to get in on the action. With all that competition, you've got to step up your game if you want to stand out.&lt;/p&gt;

&lt;p&gt;I mean, let's be real here. The tech industry is like a gladiator arena. And if you're not armed to the teeth with skills and ethics, you're going to get eaten alive by the lions. There are people out there who work their fingers to the bone just to stay ahead of the pack. They're the ones who burn the midnight oil and drink enough coffee to power a small village. And you know what? Sincerely, they're the ones who get the job done.&lt;/p&gt;

&lt;p&gt;Now, I'm not saying you've got to go all crazy and work yourself into an early grave. That's just plain silly. But you've also got to be aware that there's no time to dilly-dally in this industry. You've got to strike while the iron is hot, or you'll be left in the dust faster than you can say "Java Script" 🤣.&lt;/p&gt;

&lt;p&gt;And here's a little secret for you: having a poor work ethic is like trying to run a marathon with two left feet. It's just not going to work. If you want to succeed in tech, you've got to be willing to put in the effort and produce high-quality work. Otherwise, you'll be nothing but a flash in the pan.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Inadequate skills
&lt;/h3&gt;

&lt;p&gt;Are you still wearing your baby clothes in this ever-evolving world of technology? Just like your little one, technology is constantly growing and changing. And if you're not keeping up with the latest skills and knowledge, you might find yourself falling behind.&lt;/p&gt;

&lt;p&gt;I should know - I've missed out on some big opportunities because of inadequate skills. And you probably have too. The truth is, you can't afford to be complacent in the tech industry. If you're not constantly learning and exploring new technologies, you'll quickly become irrelevant.&lt;/p&gt;

&lt;p&gt;Take TypeScript, for example. If you're still stuck on plain old JavaScript, you're missing out on some serious opportunities. TypeScript is where the road is headed nowadays, and if you're not on board, you've got to be.&lt;/p&gt;

&lt;p&gt;You can master a skill, but don't stay stuck. The tech world is meant to be explored, so go out there and get your hands dirty. Learn something new every day, challenge yourself, and embrace the ever-evolving landscape of technology. Who knows, you might just surprise yourself with what you're capable of!&lt;/p&gt;

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

&lt;h3&gt;
  
  
  4. Lack of networking
&lt;/h3&gt;

&lt;p&gt;If you want to make it big in this industry, you've got to understand one thing: connections are key. That's right, building relationships with other techies is like having a secret weapon in your back pocket.&lt;/p&gt;

&lt;p&gt;Trust me, I'm sure about this one. It was my connection on LinkedIn who gave me my first gig as a junior developer. No interview, no nothing. And let me tell you, that kind of opportunity is priceless.&lt;/p&gt;

&lt;p&gt;I've seen plenty of techies who have all the skills and know-how, but they can't seem to make the right connections. That's a recipe for disaster. Without a strong network, you'll miss out on all kinds of opportunities for mentorship, job offers, and collaborations that can take your career to the next level.&lt;/p&gt;

&lt;p&gt;Now, I get it. For some of you out there, networking can be intimidating. You might feel like a fraud or an imposter, and that can make it hard to put yourself out there but we've all been there. The only way to get past those feelings is to jump in with both feet and start building those connections. You can make some truly amazing connections that will help you succeed in ways you never thought possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Poor communication skills
&lt;/h3&gt;

&lt;p&gt;Collaboration and teamwork are as essential in tech as caffeine is to programmers. Without communication, you're as good as a solo developer stranded on a deserted island with no Wi-Fi. In an industry that's all about brainstorming, problem-solving, and building trust, good communication skills are KEY to success.&lt;/p&gt;

&lt;p&gt;And don't think that nailing technical skills alone will land you a job. During an interview, interviewers are also assessing your ability to work in a team. If you can't communicate effectively, you'll be about as employable as a Windows 95 developer in 2023. Studies show that those with poor communication skills may struggle to keep up with the pace of the industry and limit their own success. So, study, learn, and speak up or risk being left behind in the tech dust.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  6. Inability to learn from mistakes
&lt;/h3&gt;

&lt;p&gt;In the tech industry, failure is like the annoying coworker who just won't leave you alone. You can't escape it! But don't worry, failure is not the end, it's just a stepping stone to success. Those who can't handle failure and learn from their mistakes are like a computer without an "undo" button, useless!&lt;/p&gt;

&lt;p&gt;The path to success is rarely a smooth one. It's important to remember that failure is a natural part of the journey. No one has ever succeeded in tech without experiencing setbacks, rejections, and making mistakes along the way. The key is to learn from those failures and use them as an opportunity to grow and improve.&lt;/p&gt;

&lt;p&gt;One of the biggest mistakes that people make is getting stuck in a rut after experiencing failure. Instead of learning from their mistakes and making the necessary changes, they get discouraged and give up on their dreams of a successful tech career. This can be especially true for those who have invested a lot of time and effort into a particular technology or skill, only to find out that it's no longer relevant or in demand.&lt;/p&gt;

&lt;p&gt;This is where flexibility comes in. It's important to stay flexible and adaptable in the ever-evolving tech industry. This means being willing to learn new skills and technologies, even if it means letting go of old ones. It also means being open to feedback and constructive criticism, and using that feedback to improve your work.&lt;/p&gt;

&lt;p&gt;Ultimately, the most successful tech professionals are those who are able to persevere in the face of adversity. They are the ones who keep pushing forward, even when things get tough. They don't let failure define them, but instead use it as motivation to work harder and smarter. So if you want to succeed in tech, be prepared to fail, but also be prepared to learn, grow, and adapt along the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi86zuv2z8h3boyonmky.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi86zuv2z8h3boyonmky.gif" alt="Failure is part of the game."&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Success in tech requires more than just hard work and luck. It also requires a strong mindset and a willingness to take risks. The tech industry is constantly evolving and those who are unwilling to take risks and try new things may find themselves left behind. You need to be open-minded, flexible, and adaptable to change. Don't be afraid to step out of your comfort zone and try something new. Embrace the challenge and use it to push yourself to new heights.&lt;/p&gt;

&lt;p&gt;Keypoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The psychology of success in tech is a beast that will make you work harder than a caffeinated squirrel on a mission.&lt;/li&gt;
&lt;li&gt;If you're lucky, you won't have to work forever, and you can retire to Bali with all the coconuts and sunshine you can handle.&lt;/li&gt;
&lt;li&gt;Those tech gurus on social media didn't achieve success overnight, unless they have some secret time machine we don't know about.&lt;/li&gt;
&lt;li&gt;Luck is like a chocolate teapot - useless unless you're prepared to make the most of it.&lt;/li&gt;
&lt;li&gt;As you build your tech skills and knowledge, document your journey like a pro Instagram influencer. Except instead of posing with avocado toast, show off your coding progress.&lt;/li&gt;
&lt;li&gt;Build your connections like a spider web, and you'll catch opportunities like flies.&lt;/li&gt;
&lt;li&gt;Go to meetups and hackathons like you're on a mission from Elon Musk himself.&lt;/li&gt;
&lt;li&gt;Volunteer like a superhero and solve problems like a tech wizard, and you'll be one step closer to a workspace that will make your momma proud.&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;p&gt;Also, remember to take care of yourself along the way. Burnout is a real issue in the tech industry, and pushing yourself too hard without taking breaks can be detrimental to your mental and physical health. So, take breaks when you need them, exercise, eat well, and make sure you are getting enough sleep.&lt;/p&gt;

&lt;p&gt;Success in tech is possible for anyone who is willing to put in the work, learn from their mistakes, and keep pushing forward. It's not easy, but with the right mindset and determination, you can achieve great things and create a fulfilling and rewarding career in the tech industry.&lt;/p&gt;

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

&lt;p&gt;That's all for now peeps! If you enjoyed reading this, hit me up here or on &lt;a href="https://twitter.com/JeffreySunny1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; for more tech tips and witty banter. And if you have any burning questions or thoughts to share, don't be shy to drop them in the comments - I love hearing from you all! Enjoy the journey.&lt;/p&gt;

&lt;p&gt;Image credits: &lt;a href="https://pinterest.com" rel="noopener noreferrer"&gt;Pinterest&lt;/a&gt; and &lt;a href="https://tenor.com" rel="noopener noreferrer"&gt;Tenor&lt;/a&gt;&lt;/p&gt;

</description>
      <category>motivation</category>
      <category>technology</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Crush Your React and Redux Interview: 20+ Top Questions and Strategies</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Tue, 02 May 2023 10:47:41 +0000</pubDate>
      <link>https://dev.to/jeffsalive/crush-your-react-and-redux-interview-20-top-questions-and-strategies-5226</link>
      <guid>https://dev.to/jeffsalive/crush-your-react-and-redux-interview-20-top-questions-and-strategies-5226</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
React Questions

&lt;ul&gt;
&lt;li&gt;1. What is React?&lt;/li&gt;
&lt;li&gt;2. What do you like and dislike about React?&lt;/li&gt;
&lt;li&gt;3. What do you understand by conditional rendering and list rendering?&lt;/li&gt;
&lt;li&gt;4. What is the significance of having the key prop when rendering a list of items in React?&lt;/li&gt;
&lt;li&gt;5. What is the potential bug you can introduce when using index of an array as a key?&lt;/li&gt;
&lt;li&gt;6. What is prop drilling and how can you avoid that using the React context API?&lt;/li&gt;
&lt;li&gt;7. What was the need for React Hooks?&lt;/li&gt;
&lt;li&gt;8. Explain the usage of useState, useEffect and useContext&lt;/li&gt;
&lt;li&gt;9. How do you optimize a React application?&lt;/li&gt;
&lt;li&gt;10. What are pure components in React?&lt;/li&gt;
&lt;li&gt;11. What is React memo?&lt;/li&gt;
&lt;li&gt;12. What is useMemo and useCallback in React? Outline their differences.&lt;/li&gt;
&lt;li&gt;13. How do you share logic across components in React?&lt;/li&gt;
&lt;li&gt;14. What are some of the packages you use along with React?&lt;/li&gt;
&lt;li&gt;15. What is React virtual DOM and differentiate it from the real DOM?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Redux Questions

&lt;ul&gt;
&lt;li&gt;16. What is Redux?&lt;/li&gt;
&lt;li&gt;17. How do you decide whether to choose React Context API or Redux?&lt;/li&gt;
&lt;li&gt;18. What is your understanding of redux store, actions, action creators and reducers?&lt;/li&gt;
&lt;li&gt;19. What is the control flow between the Redux store, actions, action creators and reducers?&lt;/li&gt;
&lt;li&gt;20. What does the connect function do from the react-redux library?&lt;/li&gt;
&lt;li&gt;21. Why should you dispatch an action to update the state and modify it directly?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Tips&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;React is one of the most popular front-end frameworks in the world, and as a result, React interviews are highly competitive. Whether you're an experienced React developer or just starting out, preparing for an interview can be daunting. In this post, I'll provide you with the top questions and strategies to help you crush your React interview. By the end of this post, you'll have the confidence and knowledge you need to ace any React interview and land your dream job. So, let's dive in and get you ready to impress!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;🚧 This is not an exhaustive list by any means but it's a list you should definitely be ready for 🚧&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  React Questions
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  1. What is React?
&lt;/h3&gt;

&lt;p&gt;Typically, the first question in a React interview is about React's definition. However, it's crucial that your response goes beyond just defining React. To demonstrate your comprehension of React, it's essential to explain it in a straightforward manner.&lt;/p&gt;

&lt;p&gt;👇👇&lt;br&gt;
React is a popular JavaScript library used for building user interfaces (UIs) in web applications. It was developed by Facebook and is now maintained by a community of developers. React uses a component-based approach, where each UI element is broken down into smaller, reusable components that can be easily managed and manipulated.&lt;/p&gt;

&lt;p&gt;One of the main advantages of React is that it allows developers to write code in a declarative way, meaning they can describe what the UI should look like at any given point in time, and React takes care of updating the actual UI to reflect those changes. This makes it much easier to build complex, interactive UIs that respond quickly to user input.&lt;/p&gt;

&lt;p&gt;React also has a number of other features that make it a powerful tool for web development, including virtual DOM (Document Object Model) manipulation, server-side rendering, and the ability to easily integrate with other libraries and frameworks. It is often used in conjunction with other front-end technologies such as Redux for state management, and React Native for building mobile applications.&lt;/p&gt;

&lt;p&gt;Overall, React is a flexible and powerful tool for building complex and dynamic user interfaces, and it is widely used in the web development community.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. What do you like and dislike about React?
&lt;/h3&gt;

&lt;p&gt;So, when you're in a React interview and the interviewer asks, "What do you like and dislike about React?" they want to know your thoughts and experience with the React library. They're basically trying to see if you can evaluate technology and how familiar you are with it.&lt;/p&gt;

&lt;p&gt;The interviewer also wants to know how interested and excited you are about React. Your answer can show whether you're genuinely passionate about it or if you're just using it because it's trendy right now.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;I like the unidirectional flow parent to child and the fact that React is pretty much JavaScript. Since JavaScript is at the heart of web development, React makes building web apps a lot more enjoyable and straightforward.&lt;/li&gt;
&lt;li&gt;An additional reason why I appreciate React is its ease of adoption. Through my experience working on existing codebases, I have found React code to be relatively comprehensible, making it a promising technology for new projects or team members who are not yet familiar with the codebase.&lt;/li&gt;
&lt;li&gt;I struggled initially to grasp React Server Components (RSC) and JSX, and I found that to be a bit frustrating. However, despite this, I still consider React to be my preferred library for building user interfaces.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. What do you understand by conditional rendering and list rendering?
&lt;/h3&gt;

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

&lt;p&gt;Conditional rendering and list rendering are two really useful concepts in React that let you show different things on your web page depending on what's happening or what data you have.&lt;/p&gt;

&lt;p&gt;Conditional rendering means you can decide whether to show one thing or another based on certain conditions. For example, if someone is logged in to your site, you might show them a "log out" button, but if they're not logged in, you might show them a "log in" button instead.&lt;/p&gt;

&lt;p&gt;List rendering is all about showing a bunch of things on your page that are all based on the same kind of data. You can use it to show a list of blog posts, for example, or a list of products for sale.&lt;/p&gt;

&lt;p&gt;Both of these techniques are really important for making your web page more dynamic and interactive. By using them, you can make your site respond in real-time to user actions and data changes.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. What is the significance of having the key prop when rendering a list of items in React?
&lt;/h3&gt;

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

&lt;p&gt;When you're using React to show a list of items on your web page, it's really important to include a "key" prop for each item in the list. &lt;/p&gt;

&lt;p&gt;Basically, the "key" prop is a way for React to keep track of which item is which in your list. It helps React to know which items have been added, removed, or updated when you change the data in your list.&lt;/p&gt;

&lt;p&gt;Without the "key" prop, React might get confused and not update your list correctly. For example, if you add a new item to your list, React might think that all the other items have changed too, and it might try to re-render the whole list, which could make your page slow down or even crash!&lt;/p&gt;

&lt;p&gt;So, including a "key" prop for each item in your list is really important if you want your web page to be fast, responsive, and reliable. It's a small thing, but it can make a big difference!&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  5. What is the potential bug you can introduce when using index of an array as a key?
&lt;/h3&gt;

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

&lt;p&gt;In React, when you're rendering a list of items, you need to give each item a unique "key" prop. This helps React to keep track of which item is which and update the list correctly when you change the data.&lt;/p&gt;

&lt;p&gt;Well, it turns out that using the index as the "key" prop can actually introduce a potential bug. Here's why:&lt;/p&gt;

&lt;p&gt;Let's say you have a list of items, and you remove the first item from the list. Now, all the other items shift down by one position in the array, so their indexes change. But if you're using the index as the "key" prop, React will still think that each item has the same key as before. This can cause React to get confused and not update the list correctly, leading to bugs and unexpected behavior.&lt;/p&gt;

&lt;p&gt;So, the bottom line is: don't use the index of the array as the "key" prop in React! Instead, try to use a unique identifier for each item, like a database ID or some other value that won't change if the data changes. This will help ensure that your list rendering is reliable and bug-free.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  6. What is prop drilling and how can you avoid that using the React context API?
&lt;/h3&gt;

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

&lt;p&gt;Prop drilling is a common problem in React that happens when you have to pass data down through several layers of components, even if some of those components don't need that data. This can make your code messy and hard to manage, and it's often called "prop drilling" because you end up drilling the same props down through multiple layers of your component tree.&lt;/p&gt;

&lt;p&gt;The context API lets you pass data down through your component tree without having to drill it through every layer manually. Instead, you can define a "context" object at a higher level in your component tree, and then any component below that level can access that context object without having to pass it down through props.&lt;/p&gt;

&lt;p&gt;This can make your code much cleaner and easier to manage, because you don't have to worry about passing props through layers of components that don't need them.&lt;/p&gt;

&lt;p&gt;To use the context API, you define a "provider" component that creates a new context object and sets its value to whatever data you want to pass down. Then, any component below that provider in the tree can access the context object using a "consumer" component.&lt;/p&gt;

&lt;p&gt;So, the bottom line is: if you find yourself prop drilling in React, consider using the context API to avoid that mess! It can make your code more organized and easier to work with.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  7. What was the need for React Hooks?
&lt;/h3&gt;

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

&lt;p&gt;Before React Hooks came along, managing state and lifecycle methods in React could be a bit messy and confusing. You had to use class components to manage state and lifecycle, which could make your code verbose and hard to understand.&lt;/p&gt;

&lt;p&gt;React Hooks were introduced to make it easier and more intuitive to manage state and lifecycle in React functional components. Hooks are essentially functions that let you "hook into" React's state and lifecycle features, without needing to use class components.&lt;/p&gt;

&lt;p&gt;With hooks, you can now use state and lifecycle methods in functional components just as easily as you could in class components, making your code more concise and readable. Plus, hooks give you new capabilities that weren't available before, such as the ability to use state in custom hooks and reuse logic across multiple components.&lt;/p&gt;

&lt;p&gt;In short, React Hooks were created to simplify the process of managing state and lifecycle in React functional components, and to give developers more flexibility and power in how they manage their React applications.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  8. Explain the usage of useState, useEffect and useContext
&lt;/h3&gt;

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

&lt;p&gt;useState, useEffect, and useContext are three important React hooks that are frequently used in React development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useState&lt;/strong&gt; is a hook that lets you add state to your functional components. You call useState with an initial value, and it returns an array with two values: the current state value, and a function to update that state value. You can use this state value to store data and update it as needed, just like you would with class components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useEffect&lt;/strong&gt; is a hook that lets you perform side effects in your components. Side effects are actions that don't directly affect the UI, but might involve things like fetching data from a server, updating the document title, or setting up event listeners. You can use useEffect to run code in response to changes in your component's state or props, or to run code just once when the component mounts or unmounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useContext&lt;/strong&gt; is a hook that lets you access a context object from any component in your component tree, without having to pass that object down through props. You can create a context object using the createContext function, and then use the useContext hook to access that object's value in any component that needs it.&lt;/p&gt;

&lt;p&gt;These three hooks are essential for building complex, data-driven React applications!&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  9. How do you optimize a React application?
&lt;/h3&gt;

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

&lt;p&gt;Optimizing a React application involves improving its performance, reducing load times, and making it more efficient. There are several techniques and tools you can use to optimize a React app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Code splitting: This technique involves breaking your app's code into smaller chunks that can be loaded on demand, rather than all at once. This can improve your app's load time and performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memoization: This technique involves caching the results of expensive function calls, so that they don't have to be recomputed every time the component renders. This can improve your app's rendering performance and reduce its CPU usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server-side rendering: This technique involves rendering your app's initial HTML on the server, before sending it to the client. This can improve your app's load time and SEO, and also reduce its initial data transfer size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance profiling: This involves using tools like the React Profiler or Chrome DevTools to identify performance bottlenecks in your app, and then optimizing those areas for better performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lazy loading: This technique involves loading components or data on demand, rather than all at once. This can reduce your app's initial load time and improve its performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using a state management library: If your app has complex state management requirements, using a library like Redux or MobX can help you manage that state more efficiently and improve your app's performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In addition, the key is to identify areas where your app is slow or inefficient, and then apply the appropriate optimization techniques to improve its performance and user experience.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  10. What are pure components in React?
&lt;/h3&gt;

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

&lt;p&gt;In React, pure components are components that only render based on their props and state. They don't rely on any external factors or internal state changes to decide whether to re-render.&lt;/p&gt;

&lt;p&gt;Pure components are also known as "dumb" components, because they don't have any logic or side effects of their own. They simply receive data as props and render it to the screen.&lt;/p&gt;

&lt;p&gt;The main advantage of using pure components is that they can improve your app's performance, because they only re-render when their props or state change. This can help reduce unnecessary re-renders and improve your app's overall efficiency.&lt;/p&gt;

&lt;p&gt;To create a pure component in React, you can either extend the React.PureComponent class, or use the React.memo higher-order component. React.memo is a function that accepts a component and returns a new component that only re-renders when its props change. You can use this function to optimize your components and reduce unnecessary re-renders.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  11. What is React memo?
&lt;/h3&gt;

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

&lt;p&gt;React memo is a higher-order component in React that helps optimize the performance of your components by reducing unnecessary re-renders. It works by caching the result of a component's rendering, and only re-rendering it when its props change.&lt;/p&gt;

&lt;p&gt;React memo is similar to React.PureComponent, but it's a functional component that accepts another component as its argument, and returns a new component that is optimized for performance.&lt;/p&gt;

&lt;p&gt;To use React memo, you can wrap your component in the memo function and pass it as an argument. For example:&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;memo&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;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// your component logic here&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  12. What is useMemo and useCallback in React? Outline their differences.
&lt;/h3&gt;

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

&lt;p&gt;In React, useMemo and useCallback are two hooks that can help optimize the performance of your components by memoizing expensive function calls.&lt;/p&gt;

&lt;p&gt;useMemo is a hook that memoizes the result of a function call, and only re-runs that function if its dependencies change. This can be useful for expensive calculations or operations that are used in your component's rendering logic.&lt;/p&gt;

&lt;p&gt;Here's an example of using useMemo to memoize an expensive calculation:&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;useMemo&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;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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;// expensive calculation here&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="cm"&gt;/* result of calculation */&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="cm"&gt;/* array of dependencies */&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="c1"&gt;// use result in component rendering&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;useCallback, on the other hand, is a hook that memoizes a function definition, and only re-creates that function if its dependencies change. This can be useful for optimizing child components that rely on callbacks from a parent component.&lt;/p&gt;

&lt;p&gt;Here's an example of using useCallback to memoize a function:&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;useCallback&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;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&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;// function logic here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/* array of dependencies */&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleButtonClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The main difference between useMemo and useCallback is that useMemo memoizes the result of a function call, while useCallback memoizes the function definition itself. Additionally, useCallback is usually used for optimizing child components that rely on callbacks from a parent component, while useMemo is more commonly used for expensive calculations or operations that are used in your component's rendering logic.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  13. How do you share logic across components in React?
&lt;/h3&gt;

&lt;p&gt;This is a question that can assist the interviewer in gauging the level of reusability in your React code.&lt;/p&gt;

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

&lt;p&gt;Sharing logic across components in React can be accomplished in a few different ways. Here are a few common approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Higher-order components (HOCs): A higher-order component is a function that takes a component as an argument and returns a new component with additional functionality. You can use HOCs to share common functionality across multiple components without duplicating code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Render props: A render prop is a function that a component uses to share its state or functionality with another component. The component with the render prop provides a function as a prop, and the component that uses it can call that function to access the shared logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom hooks: A custom hook is a function that encapsulates reusable logic that can be shared across multiple components. Custom hooks can be used to abstract away complex logic and make it easier to reuse in different parts of your application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's an example of how you might use a custom hook to share logic across multiple components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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;const&lt;/span&gt; &lt;span class="nx"&gt;useCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;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="nx"&gt;initialCount&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;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="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="k"&gt;return&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;increment&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;increment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCounter&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="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="na"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;increment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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="na"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="s2"&gt;`useCounter`&lt;/span&gt; &lt;span class="nx"&gt;custom&lt;/span&gt; &lt;span class="nx"&gt;hook&lt;/span&gt; &lt;span class="nx"&gt;encapsulates&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;logic&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;counting&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;incrementing&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Both&lt;/span&gt; &lt;span class="s2"&gt;`ComponentA`&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="s2"&gt;`ComponentB`&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;same&lt;/span&gt; &lt;span class="s2"&gt;`useCounter`&lt;/span&gt; &lt;span class="nx"&gt;hook&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;share&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;logic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;but&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;different&lt;/span&gt; &lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  14. What are some of the packages you use along with React?
&lt;/h3&gt;

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

&lt;p&gt;When working with React, there are a number of packages that can be helpful to include in your project. Here are a few examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;React Router: A package that provides routing capabilities to a React application, allowing you to navigate between different pages or views.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redux: A state management library that helps manage complex application state in a predictable way, making it easier to reason about and debug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Axios: A package that provides an easy-to-use interface for making HTTP requests, making it simple to communicate with a server or API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Formik: A package that simplifies the process of building and validating forms in React, making it easier to handle user input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Styled Components: A package that allows you to write CSS in your JavaScript code, making it easier to style components in a reusable and maintainable way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React Native: A framework for building native mobile apps using React, allowing you to use your existing React knowledge to build iOS and Android apps.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;There are many other packages available that can be useful when working with React. The specific packages you choose to use will depend on your specific use case and the requirements of your project.&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  15. What is React virtual DOM and differentiate it from the real DOM?
&lt;/h3&gt;

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

&lt;p&gt;In React, the virtual DOM is a lightweight representation of the actual DOM (Document Object Model) that the browser uses to render web pages. The virtual DOM is an abstraction layer that allows React to update the UI more efficiently, without directly manipulating the real DOM.&lt;/p&gt;

&lt;p&gt;Here are a few key differences between the virtual DOM and the real DOM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Performance: The virtual DOM is faster than the real DOM because it reduces the number of updates needed to keep the UI in sync with the application state. When an update occurs, React compares the new virtual DOM tree with the old one and calculates the minimal set of changes needed to update the real DOM. This is much faster than updating the entire real DOM tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manipulation: The virtual DOM can be manipulated more easily than the real DOM, which can be slow and error-prone. In React, you can update the virtual DOM directly using JSX syntax, which is then converted into a virtual DOM tree. This allows you to focus on the application logic rather than the intricacies of DOM manipulation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory usage: The virtual DOM is less memory-intensive than the real DOM because it only stores a lightweight representation of the DOM tree in memory. This means that React applications can handle large amounts of data and complex UIs without running out of memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rendering: The virtual DOM provides a declarative way to describe the UI, which makes it easier to reason about and test. In React, you declare what the UI should look like, and React takes care of rendering it efficiently to the real DOM.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




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

&lt;h2&gt;
  
  
  Redux Questions
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  16. What is Redux?
&lt;/h3&gt;

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

&lt;p&gt;Redux is an open-source JavaScript library for managing the state of a web application. It is often used with React, but can also be used with other frameworks or libraries. Redux follows a unidirectional data flow pattern, where all data in the application flows in a single direction. The state of the application is stored in a single store, which is managed by reducers. Actions are dispatched to the store to modify the state, and views are updated accordingly.&lt;/p&gt;

&lt;p&gt;One of the main benefits of Redux is that it makes it easier to manage complex application state in a predictable way, making it easier to reason about and debug. It also allows for better separation of concerns, as the state management logic is decoupled from the UI components.&lt;/p&gt;

&lt;p&gt;Redux can be used with a variety of front-end and back-end technologies, and has a large ecosystem of extensions and middleware that can be used to add additional functionality. However, it can add additional complexity to a project, and may not be necessary for smaller applications with simpler state management needs.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  17. How do you decide whether to choose React Context API or Redux?
&lt;/h3&gt;

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

&lt;p&gt;Deciding whether to use React Context API or Redux in a project can depend on a number of factors. Here are some things to consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Size and complexity of the application: If the application is relatively small or simple, it may not require the additional complexity of Redux. React Context API may be a simpler and more lightweight solution for managing state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data sharing needs: If the data in the application needs to be shared across multiple components that are not directly related to each other, Redux may be a better fit. React Context API is better suited for sharing data between components that are closely related to each other, such as parent and child components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time and resources: If you have limited time or resources, it may be more efficient to use React Context API, as it is built into React and requires less setup than Redux. However, if you have the time and resources to invest in setting up Redux, it can provide more advanced features and better scalability in the long run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Familiarity with Redux: If you or your team are already familiar with Redux and have experience using it, it may be easier to use Redux in your project. On the other hand, if you or your team are new to Redux, it may be more efficient to use React Context API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;The decision of whether to use React Context API or Redux will depend on the specific needs of your project, as well as your own preferences and experience. It may be helpful to prototype the application using both approaches to determine which one works best for your specific use case.&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  18. What is your understanding of redux store, actions, action creators and reducers?
&lt;/h3&gt;

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

&lt;p&gt;In Redux, the state of the application is stored in a single object called the &lt;strong&gt;store&lt;/strong&gt;. The store is managed by reducers, which are functions that specify how the state should be modified in response to actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actions&lt;/strong&gt; are plain JavaScript objects that describe what happened in the application. They typically have a type property that indicates the type of action that occurred, as well as any additional data that is needed to update the state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action creators&lt;/strong&gt; are functions that create and return action objects. They are often used to encapsulate the logic for creating actions and can also perform additional processing before returning the action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reducers&lt;/strong&gt; are functions that take the current state and an action as input, and return a new state object as output. Reducers are responsible for updating the state in response to actions, and should not modify the original state object directly.&lt;/p&gt;

&lt;p&gt;Together, they form the core of the Redux architecture and provide a predictable and scalable way to manage state in a web application.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  19. What is the control flow between the Redux store, actions, action creators and reducers?
&lt;/h3&gt;

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

&lt;p&gt;In a typical Redux application, the control flow between the Redux store, actions, action creators, and reducers is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The application triggers an action by calling an action creator function. The action creator function returns a plain JavaScript object that represents the action and includes a type property that describes the type of action that occurred.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Redux store receives the action and passes it to the root reducer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The root reducer delegates the action to one or more child reducers, each of which is responsible for updating a specific part of the application state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The child reducer updates its part of the state based on the action, and returns a new state object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The root reducer combines the updated state from each child reducer into a single object, and returns the new state object to the Redux store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Redux store updates its state with the new state object, and notifies any connected components that the state has changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The connected components retrieve the updated state from the Redux store, and re-render as needed to reflect the new state.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  20. What does the connect function do from the react-redux library?
&lt;/h3&gt;

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

&lt;p&gt;The &lt;code&gt;connect&lt;/code&gt; function from the &lt;code&gt;react-redux&lt;/code&gt; library is used to connect a React component to the Redux store. It is a higher-order component that takes in two arguments: &lt;code&gt;mapStateToProps&lt;/code&gt; and &lt;code&gt;mapDispatchToProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mapStateToProps&lt;/code&gt; function is used to map state from the Redux store to the props of the connected component. It takes in the current state of the store and returns an object that defines the props that should be passed to the connected component. When the state of the store changes, the connected component is automatically re-rendered with the updated props.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mapDispatchToProps&lt;/code&gt; function is used to map action creators from Redux to the props of the connected component. It takes in the &lt;code&gt;dispatch&lt;/code&gt; function as an argument, which can be used to dispatch actions to the store. The &lt;code&gt;mapDispatchToProps&lt;/code&gt; function returns an object that defines the props that should be passed to the connected component. When an action is dispatched, the connected component is automatically re-rendered with the updated props.&lt;/p&gt;

&lt;p&gt;Together, these two functions allow a React component to interact with the Redux store and dispatch actions to update the state. The &lt;code&gt;connect&lt;/code&gt; function also provides additional optimizations, such as preventing unnecessary re-renders of the connected component, and ensuring that the component only re-renders when the relevant state or props have changed.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  21. Why should you dispatch an action to update the state and modify it directly?
&lt;/h3&gt;

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

&lt;p&gt;In a Redux application, you should always dispatch an action to update the state, rather than modifying it directly. Here are a few reasons why:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Predictable state updates: By dispatching an action, you ensure that the state is updated in a predictable and consistent way. The action contains a description of what happened, which makes it easier to debug and understand how the state changed over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time travel debugging: When you dispatch an action, Redux records it in the store's history. This allows you to use tools like the Redux DevTools to "time travel" and inspect the state of the application at any point in time, making it easier to debug and identify issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Middleware and side effects: Dispatching an action allows you to use middleware, which can intercept and modify the action before it reaches the reducers. This is useful for handling side effects, such as making network requests or interacting with APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encapsulation and modularity: By dispatching an action, you ensure that state updates are encapsulated and modular. Each action represents a discrete change to the state, making it easier to reason about and test.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the other hand, modifying the state directly can lead to unpredictable behavior and bugs, especially as the application grows and becomes more complex. It also makes it harder to debug and understand how the state changed over time. By dispatching actions to update the state, you ensure that the application remains predictable, testable, and maintainable over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚧🚧🚧 NEVER MODIFY THE STATE DIRECTLY 🚧🚧🚧&lt;/strong&gt;&lt;/p&gt;




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

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;p&gt;It's normal to feel nervous before a job interview, but it's important to remember that you were selected for an interview because the employer saw something in your application that impressed them. So, use the interview as an opportunity to showcase your skills and knowledge, and to demonstrate why you would be a great fit for the position. Be confident, enthusiastic, and honest about your strengths and weaknesses. Remember to listen attentively to the interviewer, and ask thoughtful questions that show your interest in the company and the role. And above all, be yourself - your unique experiences, skills, and personality are what make you stand out from other candidates. Good luck with your interview!&lt;/p&gt;

&lt;p&gt;Hey folks! We've come to the end of this discussion. If you have any questions or thoughts, feel free to drop them in the comments section below. And hey, don't forget to follow me on &lt;a href="https://twitter.com/JeffreySunny1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, if you're interested, I could write a detailed tutorial on Redux. Let me know, and I'd be more than happy to do that for you. Cheers!&lt;/p&gt;

</description>
      <category>react</category>
      <category>interview</category>
      <category>webdev</category>
      <category>redux</category>
    </item>
    <item>
      <title>Welcome aboard, tag moderators! Let's rock this community together 🚀</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Mon, 24 Apr 2023 00:49:30 +0000</pubDate>
      <link>https://dev.to/jeffsalive/welcome-aboard-tag-moderators-lets-rock-this-community-together-1cnk</link>
      <guid>https://dev.to/jeffsalive/welcome-aboard-tag-moderators-lets-rock-this-community-together-1cnk</guid>
      <description>&lt;p&gt;Hey there, fellow tag moderator! 👋&lt;/p&gt;

&lt;p&gt;As one of the newest members of our tag moderator team, I wanted to give you a big warm welcome to the Dev Community. We're all thrilled to be on board and can't wait to see all the amazing things we can achieve together.&lt;/p&gt;

&lt;p&gt;As tag moderators, we play a vital role in keeping our community organized, relevant, and engaging for our members. We know that the job can be tough at times, but I'm confident that with our skills and expertise, we can make a real difference.&lt;/p&gt;

&lt;p&gt;We're all in this together and I want you to know that we're here to support each other in every step of the way. Whether you have questions, concerns, or just want to bounce some ideas around, we're always here to listen and help.&lt;/p&gt;

&lt;p&gt;So let's rock this community together! The community is excited to have us on board and can't wait to see what we can accomplish. Welcome to the team! 🙌&lt;/p&gt;

&lt;p&gt;Say hello in the comment section 🎉&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>moderators</category>
    </item>
    <item>
      <title>Lessons Learned: Adding ChatGPT to a Tic-Tac-Toe Game in Next.js</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Fri, 14 Apr 2023 13:31:06 +0000</pubDate>
      <link>https://dev.to/jeffsalive/lessons-learned-adding-chatgpt-to-a-tic-tac-toe-game-in-nextjs-20dm</link>
      <guid>https://dev.to/jeffsalive/lessons-learned-adding-chatgpt-to-a-tic-tac-toe-game-in-nextjs-20dm</guid>
      <description>&lt;p&gt;Ever since ChatGPT showed up at our doorstep, we've been seeing a ton of cool apps popping up left and right. And now with the API out, the possibilities are endless!&lt;/p&gt;

&lt;p&gt;Just the other day, I whipped up this super fun and addictive Tic-Tac-Toe game using Next.js. It's got all sorts of sound effects and animations that make it feel like you're really in the game. Give it a try.&lt;/p&gt;

&lt;p&gt;Check it out here: &lt;a href="https://tic-tac-toe-five-pi.vercel.app/" rel="noopener noreferrer"&gt;https://tic-tac-toe-five-pi.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aside from the cool animations and sound effects, I also spent quite some time working on the game logic to make it as efficient as possible. Playing against the computer (which I programmed to be my assistant) is already fun, but then I had an idea: what if the opponent was ChatGPT itself? Pretty neat, right?&lt;/p&gt;

&lt;p&gt;The game logic is based on an array with 9 elements (0-8) representing the state of the board. Each element can hold either the player's or computer's symbol, or be null, indicating an empty spot. With this in mind, I thought it'd be cool to pass the board's state to the &lt;a href="https://platform.openai.com/docs/api-reference/completions" rel="noopener noreferrer"&gt;OpenAPI Completion Endpoint&lt;/a&gt; and have AI suggest its next move by returning the index where it should place its symbol.&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%2Fq84ujhj2gwp5fnu3dmbh.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%2Fq84ujhj2gwp5fnu3dmbh.png" alt="Tic-Tac-Toe Game" width="780" height="669"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was a great idea, and technically it almost worked, but unfortunately, the implementation had some flaws. Firstly, allowing the AI to suggest the next move meant making requests to the endpoint every time, which was very slow and inefficient. After a few attempts, the response I received was "Too many requests," which essentially broke the game and ruined the fun.&lt;/p&gt;

&lt;p&gt;Secondly, when you sign up for OpenAI's APIs, you receive free credits (about $18), which had already expired in my case. Upgrading to a paid plan wasn't feasible, as releasing the app would mean thousands of requests being made.&lt;/p&gt;

&lt;p&gt;However, the game logic I created is pretty solid, and I believe the AI would suggest the same moves as the logic does. So, in the end, I decided to go with my own logic.😎. No questions asked!&lt;/p&gt;

&lt;p&gt;Do you see what I see? This could be huge for the world of gaming. In the near future, instead of writing complex game logic, developers could simply enable AI to compete against players. Just imagine playing your favorite game against a well-built AI opponent. Trust me, you'll be crushed! 😂 The possibilities are endless, and we're just scratching the surface. This AI revolution is here to stay.&lt;/p&gt;

&lt;p&gt;Thanks for reading, folks! Don't forget to follow me on &lt;a href="https://twitter.com/JeffreySunny1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;And if you're interested in a detailed guide on how I built the Tic-Tac-Toe game in Next.js, let me know in the comments!&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Maximize Your Upload Efficiency: How to Perform Parallel File Uploads with Node.js and Cloudinary</title>
      <dc:creator>Jeffrey Nwankwo</dc:creator>
      <pubDate>Fri, 07 Apr 2023 16:25:59 +0000</pubDate>
      <link>https://dev.to/jeffsalive/maximize-your-upload-efficiency-how-to-perform-parallel-file-uploads-with-nodejs-and-cloudinary-42hn</link>
      <guid>https://dev.to/jeffsalive/maximize-your-upload-efficiency-how-to-perform-parallel-file-uploads-with-nodejs-and-cloudinary-42hn</guid>
      <description>&lt;p&gt;In one of my recent projects, I was working on this really cool thing called an Order Management System (OMS). Basically, it's this centralized platform that helps NGOs automate all sorts of stuff - like managing their programs, applications, staff, students, volunteers, emails, files, and forms.&lt;/p&gt;

&lt;p&gt;Anyway, at one point in the project, I had to figure out how to handle file uploads to Cloudinary for a particular endpoint. My initial solution worked, but it was a little slow - it took about a while to upload five files at a time. As a developer, I knew I could do better, so I came up with a new solution that worked way faster.&lt;/p&gt;

&lt;p&gt;If you're using Multer, which is a really handy tool for uploading files in Node.js, here's how you can use it to upload a file to Cloudinary:&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;cloudinary&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;./cloudinary&lt;/span&gt;&lt;span class="dl"&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;upload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploader&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;uploadFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;File&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;uploadedFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/upload-folder/files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;public_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;overwrite&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="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;uploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secure_url&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;Once you've uploaded a file, you can save the result in a database. To do this, use the file's fieldname (e.g. "profileImage") as the key, and the secure_url as the value.&lt;/p&gt;

&lt;p&gt;However, sometimes you might need to upload multiple files at once. For example, if you have three file upload inputs on a page, and one of them lets the user upload up to three files, you'll have to handle a total of five files. In that case, you can use the name attribute of the input to identify which files belong together. So if the input for uploading three files is named "supportingDocuments", and the other two inputs are named "profileImage" and "resume", you can use those names to keep track of which files were uploaded where.&lt;/p&gt;

&lt;p&gt;Here's an example of what &lt;code&gt;req.files&lt;/code&gt; might look like, given the three file inputs mentioned above:&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="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fieldname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supportingDocuments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;originalname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document1.pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7bit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mimetype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Buffer 25 50 44 46 2d 31 2e 33 ... &amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fieldname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supportingDocuments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;originalname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document2.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7bit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mimetype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Buffer ff d8 ff e0 00 10 ... &amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fieldname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supportingDocuments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;originalname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document3.docx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7bit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mimetype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/vnd.openxmlformats-officedocument.wordprocessingml.document&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;987654&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Buffer 50 4b 03 04 0a 00 ... &amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fieldname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profileImage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;originalname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profile.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7bit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mimetype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Buffer ff d8 ff e0 00 10 ... &amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fieldname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resume&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;originalname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resume.pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7bit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mimetype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;876543&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Buffer 25 50 44 46 2d 31 2e 33 ... &amp;gt;&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;p&gt;So, if we have three files uploaded in the "supportingDocuments" field, and one file each in the "profileImage" and "resume" fields, how can we upload these files and save the results in a database?&lt;/p&gt;

&lt;p&gt;Here's how:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UploadApiResponse&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;cloudinary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&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;./cloudinary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;uploadFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Files&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;string&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;results&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;fieldNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;fieldNamesOccurrences&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="na"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;fieldNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/upload-folder/files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;public_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;overwrite&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="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="na"&gt;uploadResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UploadApiResponse&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;fieldNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fieldName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fieldNames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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;uploadedFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uploadResults&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;fieldNamesOccurrences&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldNamesOccurrences&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldNamesOccurrences&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secure_url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;uploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secure_url&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secure_url&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uploadedFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secure_url&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="nx"&gt;results&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;So, first of all, we need to give the &lt;code&gt;uploadFiles&lt;/code&gt; function an argument called files. (Coming from &lt;code&gt;req.files&lt;/code&gt;). This can either be an array of files or an object with field names and arrays of files. We check for this in the function.&lt;/p&gt;

&lt;p&gt;Next, we create some empty objects and arrays to help us keep track of everything. We have an empty object called &lt;code&gt;results&lt;/code&gt;, an empty array called &lt;code&gt;fieldNames&lt;/code&gt;, and another empty object called &lt;code&gt;fieldNamesOccurrences&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, for each file in the files array, we get the name of the field it's associated with and add it to the &lt;code&gt;fieldNames&lt;/code&gt; array. We also use the Cloudinary package to upload each file and push the promise of the upload to an array called &lt;code&gt;uploads&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We use a special method called Promise.all() to wait for all the file uploads to complete at once. This makes the process much faster! Once all the files are uploaded, we get an array of UploadApiResponse objects called &lt;code&gt;uploadResults&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we loop through the &lt;code&gt;fieldNames&lt;/code&gt; array and check how many times each field name appears. If it appears more than once, we add the uploaded file URL to an array in the results object that's associated with that field name. If it only appears once, we simply set the URL as a string associated with that field name in the results object.&lt;/p&gt;

&lt;p&gt;And that's pretty much it! The &lt;code&gt;uploadFiles&lt;/code&gt; function helps you upload files using Cloudinary and returns an object that shows you the URL(s) of the uploaded file(s) associated with each field name.&lt;/p&gt;

&lt;p&gt;Awesome news right? Once you get the results from the function, you can save them in your database however you want. This means that you can upload to Cloudinary and save files in your database super fast.&lt;/p&gt;

&lt;p&gt;That's all folks 😎. Like and leave your thoughts in the comment section. Feel free to follow me on &lt;a href="https://twitter.com/JeffreySunny1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloudinary</category>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
