<?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: Mikhael Esa</title>
    <description>The latest articles on DEV Community by Mikhael Esa (@mikhaelesa).</description>
    <link>https://dev.to/mikhaelesa</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%2F1173922%2Fcf905c2f-6f1b-4ae6-a84d-91cb670f0c67.jpeg</url>
      <title>DEV Community: Mikhael Esa</title>
      <link>https://dev.to/mikhaelesa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikhaelesa"/>
    <language>en</language>
    <item>
      <title>Building SUMMARIZED: How I Built a Multi-Format Knowledge Hub with Next.js and AI</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Mon, 29 Dec 2025 14:09:39 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/building-summarized-how-i-built-a-multi-format-knowledge-hub-with-nextjs-and-ai-2cg1</link>
      <guid>https://dev.to/mikhaelesa/building-summarized-how-i-built-a-multi-format-knowledge-hub-with-nextjs-and-ai-2cg1</guid>
      <description>&lt;p&gt;We live in an era of information overload. We buy books we never open and save podcasts we never listen to. The intention is there—we want to learn—but the time simply isn't.&lt;/p&gt;

&lt;p&gt;I noticed that people (myself included) often struggle to finish the content they consume. They might read the first chapter or listen to the first 10 minutes, but life gets in the way. I wanted to solve this by building &lt;strong&gt;SUMMARIZED&lt;/strong&gt;: a platform that digests heavy content into accessible formats like video, audio, text, slides, and infographics.&lt;/p&gt;

&lt;p&gt;Here is the story behind how I built it, the tech stack I used, and the surprising lessons I learned about working with AI.&lt;/p&gt;

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

&lt;p&gt;To get this off the ground quickly without sacrificing performance, I stuck to a robust, modern stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend &amp;amp; Storage:&lt;/strong&gt; Supabase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the web framework was standard, the real challenge was the &lt;strong&gt;content generation pipeline&lt;/strong&gt;. How do you take a 300-page book and turn it into a slide deck or a podcast script automatically?&lt;/p&gt;

&lt;h3&gt;
  
  
  The Secret Weapon: NotebookLM
&lt;/h3&gt;

&lt;p&gt;I realized I didn't need to build a custom LLM pipeline from scratch when &lt;strong&gt;Google’s NotebookLM&lt;/strong&gt; existed. It became the engine of the operation.&lt;/p&gt;

&lt;p&gt;My workflow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I gather the source material (books, articles, transcripts).&lt;/li&gt;
&lt;li&gt;I feed them into NotebookLM.&lt;/li&gt;
&lt;li&gt;I prompt it to generate summaries in specific formats: an audio overview, a video script, a slide deck outline, textual takeaways, and data for infographics.&lt;/li&gt;
&lt;li&gt;I export these assets and upload them to my database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Storage Constraint&lt;/strong&gt;&lt;br&gt;
One technical hurdle I hit early on was the &lt;strong&gt;Supabase&lt;/strong&gt; free tier limit. Storing audio and images adds up fast. To stay within the free tier boundaries, I had to implement an aggressive compression strategy for all assets before they hit the storage bucket. It taught me to be efficient with data right from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accelerating UI/UX with AI
&lt;/h2&gt;

&lt;p&gt;I am a developer, not a UI designer. In the past, I would have spent weeks agonizing over padding and color palettes. This time, I leveraged AI design tools like &lt;strong&gt;Lovable&lt;/strong&gt;, &lt;strong&gt;Bubble.io&lt;/strong&gt;, &lt;strong&gt;v0&lt;/strong&gt;, and &lt;strong&gt;Stitch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This was a game-changer. Instead of designing components pixel-by-pixel, I described what I needed, and the AI generated the UI code in minutes. This allowed me to focus entirely on my area of expertise: the logic and the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Google Antigravity" Framework
&lt;/h2&gt;

&lt;p&gt;To keep the project grounded, I used &lt;strong&gt;Google Antigravity&lt;/strong&gt; to help build the project based on a set of fundamental rules I had written.&lt;/p&gt;

&lt;p&gt;If you've ever coded with AI, you know it can hallucinate or drift off-topic. By establishing strict "rules of gravity" (fundamentals) for the project, I ensured the AI assistants stayed aligned with the project's core architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Building &lt;em&gt;SUMMARIZED&lt;/em&gt; taught me two massive lessons about modern software development.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Rules Are Everything for AI
&lt;/h3&gt;

&lt;p&gt;The most time-consuming part of this project wasn't coding—it was defining the &lt;strong&gt;rules&lt;/strong&gt;.&lt;br&gt;
I learned that if you want AI to build complex software, you cannot just say "build this." You need to provide a rigid framework of rules. Once I nailed down these rules, the AI's output became streamlined and predictable.&lt;/p&gt;

&lt;p&gt;The best part? This setup time is an investment. Now that I have these rules defined, I can reuse this "rule-set" for every future project to get up and running instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Component Libraries &amp;gt; Custom AI Components
&lt;/h3&gt;

&lt;p&gt;I initially tried to get AI to build complex UI components from scratch. It often failed or produced buggy code.&lt;/p&gt;

&lt;p&gt;I realized that &lt;strong&gt;Component Libraries&lt;/strong&gt; are the solution. AI models are excellent at reading documentation. When I instructed the AI to use a specific library and provided the docs, the output was flawless. Documentation provides the context that trial-and-error simply can't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts &amp;amp; Try It Out
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SUMMARIZED&lt;/strong&gt; started as a way to help people consume content, but building it became a masterclass in how to leverage AI for development. By combining Next.js with NotebookLM and a rule-based AI workflow, I was able to ship a complex product in a fraction of the time it would usually take.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to see the result in action?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you want to inspect the build or simply catch up on your reading list without spending hours, check out the live application here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://summarized.vercel.app" rel="noopener noreferrer"&gt;https://summarized.vercel.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>learning</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>A Breath of Fresh Air Amidst Framework Fatigue and Burnout</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Tue, 27 May 2025 14:37:55 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/a-breath-of-fresh-air-amidst-framework-fatigue-and-burnout-552g</link>
      <guid>https://dev.to/mikhaelesa/a-breath-of-fresh-air-amidst-framework-fatigue-and-burnout-552g</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMmZ0Nzg2Z2xzOXIzcTAzNWo3dTRpaW95bTVsdWxpN2dtY3Z0bmJoYyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FzyjCXPXNo39i0CB467%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMmZ0Nzg2Z2xzOXIzcTAzNWo3dTRpaW95bTVsdWxpN2dtY3Z0bmJoYyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FzyjCXPXNo39i0CB467%2Fgiphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey there, and thanks for stopping by!&lt;br&gt;
I really appreciate you taking a bit of your time to read this. This post kicks off what I’m calling my “Learning Elixir Journey”, and in it, I want to share what led me to explore Elixir—especially when there are already so many hyped languages out there like Rust, Python, and others.&lt;/p&gt;

&lt;p&gt;I’ve been working as a front-end developer for nearly five years now, mostly living in the world of React and Next.js since day one. And honestly, I’m super grateful for that ecosystem—it’s helped me land a job, build a career, and support a pretty comfortable life.&lt;/p&gt;

&lt;p&gt;React’s always had a special place for me. Sure, there’s a new JavaScript framework popping up every week, but despite all the noise, I’ve stuck with React. It’s been reliable. Familiar.&lt;/p&gt;

&lt;p&gt;But lately… something’s been off.&lt;/p&gt;

&lt;p&gt;The JavaScript world moves so fast. Too fast, sometimes. Things blow up overnight and vanish just as quickly. It started to feel like I was being swept along by a current I didn’t ask to ride. I remember thinking, “Can we just slow down a bit?”&lt;/p&gt;

&lt;p&gt;See, I’m not the kind of dev who likes chasing trends or trying every new tool for the sake of it. I care more about the concepts behind the tools—architecture, design patterns, the why behind the what. And to be honest, that’s what started bugging me: too many folks around me were using tools they didn’t really understand.&lt;/p&gt;

&lt;p&gt;Take a friend of mine, for example, he’s super into state management libraries like Redux and Zustand. But when I asked him why those tools work the way they do, or what problems they’re actually solving under the hood, he didn’t really have an answer. Just a lot of surface-level enthusiasm.&lt;/p&gt;

&lt;p&gt;I used to be in that same place. And at some point, I decided I didn’t want to be that kind of developer anymore.&lt;/p&gt;

&lt;p&gt;That’s when I started building my own tools—state management, i18n, date pickers, even an ESLint plugin or two. I wanted to understand how things worked, not just use them. And you know what? I learned more than I ever expected. I don’t regret a single moment I spent going down that path.&lt;/p&gt;

&lt;p&gt;But it came at a cost.&lt;/p&gt;

&lt;p&gt;All that time I spent digging deep made me realize just how “fake” a lot of this world can feel. Shiny tools, loud opinions, surface-level understanding. I wanted something more grounded. More thoughtful. More… real.&lt;/p&gt;

&lt;p&gt;And that’s when I found Elixir.&lt;/p&gt;

&lt;p&gt;Before I stumbled upon Elixir, I was seriously considering diving into Go or Rust. I even gave both of them a try—wrote some code, followed a few tutorials—but for some reason, they just didn’t click for me.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong—both are amazing languages with strong communities and solid engineering behind them. But for whatever reason, I couldn’t find that spark, that “aha” feeling that makes you want to keep going, you know?. Maybe I’m just not ready for them yet. Maybe they just didn’t speak to the kind of developer I am right now. And that’s okay.&lt;/p&gt;

&lt;p&gt;Elixir gave me back that feeling I’d been missing for a long time like discovering a hidden gem. I guess I’m lucky I never shy away from a bit of challenge,&lt;/p&gt;

&lt;p&gt;I’ve learned so many new concepts along the way — OTP, the BEAM VM, memory compaction and fragmentation, the actor model, the difference between processes and threads — and all of it has reignited my passion for programming. It’s like my developer spirit woke up again.&lt;/p&gt;

&lt;p&gt;So yeah, I’m really excited to share my journey learning Elixir with all of you. If you’re feeling stuck or restless like I was, maybe it’s time to take a step back and search for that thing your developer soul has been craving. Trust me, when you find it, you’ll come out on the other side feeling like a whole new person.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>programming</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Building a Fullstack Application With Next.js + Prisma + SQLite</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Sun, 27 Apr 2025 13:32:47 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/building-a-fullstack-application-with-nextjs-prisma-sqlite-41hg</link>
      <guid>https://dev.to/mikhaelesa/building-a-fullstack-application-with-nextjs-prisma-sqlite-41hg</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;My first thought on Next.js was "Oh it's just another front-end framework based on React" but I was wrong. Next.js is not just another front-end framework but it is a fullstack framework. Yes you heard it right, fullstack.&lt;/p&gt;

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

&lt;p&gt;I have done some research about this topic and these 3 stacks suits me well for building a simple fullstack app. And I was blown away by how these 3 tech has a rich feature and gives me a huge boost in Developer Experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;If you are interested in reading the documentation of each technology, then here's the link to the documentations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.prisma.io/docs" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TryGhost/node-sqlite3#%EF%B8%8F-node-sqlite3" rel="noopener noreferrer"&gt;SQLite&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's go get our hands dirty.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdk5iq7o650m5dabrevt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdk5iq7o650m5dabrevt.gif" alt="Dirty Hands Gif" width="400" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;First let's go with installing a fresh next.js app with this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx create-next-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can just answer the prompts but when it prompt you to use an App router, choose no as we are going to use the OG pages router 😉.&lt;/p&gt;

&lt;p&gt;Next, we are going to setup the prisma so let's install prisma.&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing we will initialize prisma preconfigured with sqlite by running this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx prisma init &lt;span class="nt"&gt;--datasource-provider&lt;/span&gt; sqlite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will generate a prisma folder with &lt;code&gt;schema.prisma&lt;/code&gt; file init. We will put our models inside the file so let's create some models&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="nx"&gt;model&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;    &lt;span class="nx"&gt;Int&lt;/span&gt;     &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;id&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoincrement&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;unique&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;        &lt;span class="nx"&gt;Int&lt;/span&gt;     &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;id&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoincrement&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;     &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;   &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="nx"&gt;published&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&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="nx"&gt;author&lt;/span&gt;    &lt;span class="nx"&gt;User&lt;/span&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;references&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nx"&gt;authorId&lt;/span&gt;  &lt;span class="nx"&gt;Int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have created 2 models which are User and Post where these 2 models has relation to each other.&lt;/p&gt;

&lt;p&gt;We have models, now we have to create the DB in order to do CRUD.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will create a migration folder inside the prisma folder.&lt;/p&gt;

&lt;p&gt;Great! Now you have a database already setup. Next step is to create an API to do CRUD.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>prisma</category>
      <category>database</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>SSH Config for Multiple SSH Authentication</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Fri, 05 Jul 2024 12:33:49 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/ssh-config-for-multiple-ssh-authentication-58jc</link>
      <guid>https://dev.to/mikhaelesa/ssh-config-for-multiple-ssh-authentication-58jc</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Having multiple SSH keys is useful when you want to separate the purpose of each key, for example you want to have a different SSH keys for GitLab and GitHub for whatever reason. This can be achieved via the config file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Config File
&lt;/h2&gt;

&lt;p&gt;To be able to have multiple ssh for different purpose, we need to create a config file inside the .ssh directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.ssh
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;config
&lt;span class="nv"&gt;$ &lt;/span&gt;vim config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands above will directs us to the .ssh directory and creates the config file and then uses vim to edit the content. You can use other editor like nano, it's up to you.&lt;/p&gt;

&lt;p&gt;Now let's edit the config file to look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~\.ssh\my_gitlab_ssh
    IdentitiesOnly yes

Host github.com
    HostName github.com
    User git
    IdentityFile ~\.ssh\my_github_ssh
    IdentitiesOnly yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now there you have it, a ssh config file for multiple SSH keys. You are not limited to only GitHub and GitLab, you can also use it for server authentication and many more.&lt;/p&gt;

&lt;p&gt;~ Dadah 👋&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>learning</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>How to Configure ESLint for TypeScript Projects</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Tue, 18 Jun 2024 13:41:03 +0000</pubDate>
      <link>https://dev.to/jupri-organization/how-to-configure-eslint-for-typescript-projects-1aip</link>
      <guid>https://dev.to/jupri-organization/how-to-configure-eslint-for-typescript-projects-1aip</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;One thing that is important in projects but often neglected is code style and standardization. Fortunately for those who really wants to enforce certain code style or standards to their projects, eslint got our back!&lt;/p&gt;

&lt;p&gt;ESLint is quite easy to setup but when you add typescript, then the complexity increases a little bit but don't be afraid as this article will guide you through it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Essential Packages
&lt;/h2&gt;

&lt;p&gt;before we can use eslint, we must install some essential packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;eslint&lt;/strong&gt;: Provides a flexible configuration system that allows you to define custom rules or leverage existing rule sets for specific coding styles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@typescript-eslint/parser&lt;/strong&gt;: A parser plugin specifically designed for ESLint to handle TypeScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@typescript-eslint/eslint-plugin&lt;/strong&gt;: Provides a collection of ESLint rules specifically designed for TypeScript code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up the ESLint
&lt;/h2&gt;

&lt;p&gt;Now that we have installed the essential packages, we can now start creating the eslint config. Let's start by creating a file called &lt;code&gt;.eslintrc.json&lt;/code&gt; and inside the file we write the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint/parser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;parserOptions:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;sourceType:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ecmaVersion:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;parser: "@typescript-eslint/parser"&lt;/strong&gt;: This line specifies the parser ESLint should use. Setting it to @typescript-eslint/parser ensures that ESLint can understand the syntax and types specific to TypeScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plugins: ["@typescript-eslint"]&lt;/strong&gt;: This section defines the plugins used for linting. This plugin provides a collection of rules specifically designed for TypeScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"]&lt;/strong&gt;: This section defines the base configurations that our setup inherits from.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"eslint:recommended"&lt;/strong&gt;: This extends your configuration with ESLint's recommended set of rules for JavaScript code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"plugin:@typescript-eslint/recommended"&lt;/strong&gt;: This extends our configuration with the recommended set of rules from the @typescript-eslint plugin&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;sourceType: "module"&lt;/strong&gt;:This option specifies the type of source code being parsed. Here, it's set to "module", indicating that the code is expected to be written in a module system like ES modules&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;ecmaVersion: 2023&lt;/strong&gt;: This option specifies the ECMAScript version that the parser should expect the code to be written in.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;That's the configuration that we needed, as well as the explanation for each properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the Rules
&lt;/h2&gt;

&lt;p&gt;Now after setting up the ESLint, you are left with exploring the various rules of eslint and match it into your liking. You can explore the available rules in &lt;a href="https://eslint.org/docs/latest/rules/" rel="noopener noreferrer"&gt;ESLint docs&lt;/a&gt; and &lt;a href="https://typescript-eslint.io/rules/" rel="noopener noreferrer"&gt;TypeScript ESLint docs&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you don't feel like exploring the rules and want to just install a plugin, don't worry we got your back. We have made a plugin that is curated and tailored to improve your productivity, project's maintainability, and type safety. Check out our &lt;a href="https://www.npmjs.com/package/@jupri-lab/eslint-config-typescript" rel="noopener noreferrer"&gt;eslint-plugin-typescript&lt;/a&gt; as well as &lt;a href="https://www.npmjs.com/package/@jupri-lab/eslint-config-typescript-react" rel="noopener noreferrer"&gt;eslint-plugin-typescript-react&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to Setup Jest on Typescript Monorepo Projects</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Wed, 12 Jun 2024 14:38:30 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/how-to-setup-jest-on-typescript-monorepo-projects-o4d</link>
      <guid>https://dev.to/mikhaelesa/how-to-setup-jest-on-typescript-monorepo-projects-o4d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz76ij6xgu4lrtb6bffde.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz76ij6xgu4lrtb6bffde.gif" alt="Testing GIF" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;When I started making open source libraries, I didn't know much about unit testing in terms of writing the tests, and setting up the environment. There was a strong voice that told me to write unit tests for my open source libraries because if one day it gets big (hopefully) it wouldn't be efficient to test every functionality manually.&lt;/p&gt;

&lt;p&gt;Acknowledging the benefits of unit testing, I jumped right in to the one and only &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;. Honestly it overwhelms me a little bit too much when I read the docs and there are a lot of things going on in there. But I didn't lose spirit by just reading a docs, otherwise I wouldn't call myself a learner 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  The challenges
&lt;/h2&gt;

&lt;p&gt;Because it was the first time I'm learning unit testing using Jest, I'm confused on how to set things up and running in my project. Most of my projects are using typescript + monorepo structure and it requires a specific config to make it running. Without further a do, let's dive right into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;p&gt;In this section, we'll go through the steps on how to configure Jest in Typescript Monorepo project so please follow along and read the steps carefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;First of all, we have to install a few packages as devDependencies especially if we are using typescript, there are extra packages that we must install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; jest @types/jest ts-jest ts-node typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;jest:&lt;/strong&gt; Is the tool for writing unit tests and run the tests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@types/jest:&lt;/strong&gt; Contains type definitions for jest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ts-jest:&lt;/strong&gt; A Jest transformer that allows us to use Jest for testing TypeScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ts-node:&lt;/strong&gt; Allows us to run TypeScript code directly in Node.js without needing to precompile it to JavaScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;typescript:&lt;/strong&gt; You know what it is&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After installing those packages, you can check your &lt;code&gt;package.json&lt;/code&gt; to see if they are listed in &lt;code&gt;devDependencies&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest config
&lt;/h3&gt;

&lt;p&gt;Let's create a &lt;code&gt;jest.config.ts&lt;/code&gt; in the root of our project and write this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&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;@jest/types&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InitialOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transform&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;^.+&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.(ts|tsx)$&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;ts-jest&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="na"&gt;projects&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;testPathIgnorePatterns&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;&amp;lt;rootDir&amp;gt;/node_modules/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-package&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;testMatch&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;&amp;lt;rootDir&amp;gt;/packages/my-package/__tests__/**/*.spec.ts&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="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;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the explanation for each&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;verbose:&lt;/strong&gt; To show a verbose version of test reports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;preset:&lt;/strong&gt; A pre-configured set of settings and configurations for Jest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;testEnvironment:&lt;/strong&gt; The test environment that will be used for testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;transform:&lt;/strong&gt; Specifies how different types of files should be processed before running the tests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;projects:&lt;/strong&gt; Allows us to define multiple sets of configurations within a single Jest setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;testPathIgnorePatterns:&lt;/strong&gt; An array of regular expression patterns that Jest uses to ignore test files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;displayName:&lt;/strong&gt; A name to identify our project like an alias.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;testMatch:&lt;/strong&gt; Specify the glob patterns that Jest uses to detect test files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The configuration above assumes that your project structure look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| - - packages
| - - - my-package
| - - - - __tests__
| - - - - - test.spec.ts
| - tsconfig.base.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside you root &lt;code&gt;package.json&lt;/code&gt;, you can create a script to run the test on a specific project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test:my-package"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --selectProjects=my-package"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing tests
&lt;/h3&gt;

&lt;p&gt;Now assuming that you have followed the configurations above, it's time for us to create our first test case. Inside the &lt;code&gt;__tests__&lt;/code&gt; folder, create a file named &lt;code&gt;test.spec.ts&lt;/code&gt; and write a dummy test to see if the configurations work perfectly.&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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counts correctly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After writing the sample test, make sure you are in root directory and run the test script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;:my-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Unit testing using Jest is fun but can overwhelm new learners especially when configuring the Jest itself in order for it to work properly. The complexity even increases when we use different architecture such as monorepo. In spite of the complexity that Jest introduces, Jest is still a powerful testing tool that is used by many developers to test their projects, so it's worth it to learn Jest :).&lt;/p&gt;

&lt;p&gt;~ Dadah 👋&lt;/p&gt;

</description>
      <category>testing</category>
      <category>typescript</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I Achieved Maintanability, and Scalability in My Projects</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Sat, 11 May 2024 20:14:16 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/how-i-achieved-maintanability-and-scalability-in-my-projects-khe</link>
      <guid>https://dev.to/mikhaelesa/how-i-achieved-maintanability-and-scalability-in-my-projects-khe</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;As I stepped into my new role as a Frontend Developer, I encountered a disorganized landscape devoid of standardization. The codebases resembled tangled mazes, hindering rather than facilitating progress.&lt;/p&gt;

&lt;p&gt;In the world of software development, maintainability and scalability are paramount. Yet, here I was, facing a reality that contradicted these principles. Determined to effect change, I embarked on a mission to establish standards amidst the chaos.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  First Objective: Find the Correct Technologies
&lt;/h2&gt;

&lt;p&gt;While prioritizing user-friendly technologies with clear benefits sounds ideal, it can lead to oversaturating your tech stack. This complexity can create a difficult-to-manage environment with a steep learning curve, especially if you incorporate advanced tools.&lt;/p&gt;

&lt;p&gt;We took our time evaluating different options and ultimately landed on a focused set of technologies: &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;, &lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux Toolkit&lt;/a&gt;, &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;SASS&lt;/a&gt;, and &lt;a href="https://axios-http.com/docs/intro" rel="noopener noreferrer"&gt;Axios&lt;/a&gt;. This combination offers a powerful and manageable foundation for our project, avoiding the pitfalls of an overly complex tech stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second Objective: Building a Fortress
&lt;/h2&gt;

&lt;p&gt;Recognizing the importance of a well-structured project, we embarked on a deep dive into the world of architectural patterns and best practices. &lt;/p&gt;

&lt;p&gt;We explored the elegance of the Atomic Design System, which allows us to build complex UIs from reusable components. Feature-based structures provided a clear organization, ensuring each section of the project is self-contained and easy to manage. Additionally, we embraced the power of decoupling, ensuring components are independent and avoid unnecessary dependencies. File co-location kept related code physically close, fostering better maintainability. &lt;/p&gt;

&lt;p&gt;By thoughtfully combining these techniques, we meticulously crafted a robust and well-rounded project structure that will serve as a solid foundation for future development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third Objective: Code Cohesion
&lt;/h2&gt;

&lt;p&gt;Recognizing the power of a united front, we prioritized code standardization to streamline collaboration and minimize confusion within our development squad.  This meant establishing a shared codebase dialect – a set of agreements on naming conventions, standardized code boilerplate, and other essential elements. &lt;/p&gt;

&lt;p&gt;To ensure everyone speaks the same coding language, we leverage the power of ESLint and Stylelint, enforcing these rules and preventing integration nightmares down the road.  But that's not all! Husky and Lint-Staged act as our vigilant pre-commit sentinels, automatically identifying potential code quality slips before they ever reach the sacred halls of GitHub.&lt;/p&gt;

&lt;p&gt;By combining these efforts, we've forged a unified codebase, fostering a collaborative environment where developers can focus on building amazing features, not deciphering cryptic code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fourth Objective: Crafting the Code Codex
&lt;/h2&gt;

&lt;p&gt;We believe in the power of clear documentation, especially for code that will be used by others. We start by meticulously documenting our template codebase, providing a solid foundation for newcomers.  Furthermore, we encourage a culture of developer-driven documentation throughout the development process. This documentation falls into three key categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global Code Chronicles&lt;/strong&gt;: In-depth explanations for our shared codebase, ensuring everyone understands its usage and functionality.&lt;br&gt;
&lt;strong&gt;Feature Roadmaps&lt;/strong&gt;: Detailed documentation for each feature, outlining its purpose and key details. This prevents information gaps and streamlines future development.&lt;br&gt;
&lt;strong&gt;Code Snippet Sidebars (Optional)&lt;/strong&gt;: While lower priority, documentation for isolated code serves as a helpful reference, fostering overall codebase understanding.&lt;/p&gt;

&lt;p&gt;This multi-layered approach ensures a comprehensively documented codebase – a roadmap for developers of all experience levels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fifth Objective: Adapting to Challenges
&lt;/h2&gt;

&lt;p&gt;The path of software development rarely adheres to a strictly linear course. There will be times when elegant solutions demand a touch of creative deviation from the norm. Recognizing this reality, we foster a culture of continuous learning within our development team. We encourage developers to delve into the vast landscape of code patterns and best practices, equipping them with a versatile toolkit for tackling any coding challenge.&lt;/p&gt;

&lt;p&gt;In the context of our React-based project, this translates to a deep understanding of powerful patterns like compound components, Higher-Order Components (HOCs), and render props. By empowering our developers with this knowledge, we unlock a strategic advantage: the ability to tailor solutions to specific needs. Even if a solution isn't a textbook example of a particular pattern, a well-considered and well-implemented adaptation can significantly improve the long-term health of our codebase. This adaptability, combined with a foundation of best practices, allows us to prioritize maintainability without sacrificing functionality.&lt;/p&gt;

&lt;p&gt;Furthermore, we encourage a spirit of self-reliance within our team. While third-party packages offer convenience, we believe in the value of crafting custom solutions whenever feasible. This approach not only grants us greater control over our codebase but also fosters a deeper understanding of the underlying mechanisms at play. By building solutions from the ground up, developers gain invaluable insights into the intricate workings of the technologies they utilize.&lt;/p&gt;

&lt;p&gt;In essence, we weave these patterns into the fabric of our code, creating a resilient and adaptable codebase that serves as a testament to the collective ingenuity of our development team. This commitment to both adaptability and self-reliance empowers us to navigate the ever-evolving landscape of software development with creativity, efficiency, and a profound understanding of the craft.&lt;/p&gt;

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

&lt;p&gt;Many tech companies fall prey to the chaos of inconsistent code. We chose a different path – a well-defined tech stack, a fortress of organization, and the power of code standardization. By fostering a culture of continuous learning and self-reliance, we've built a codebase that's not just functional, but a foundation for future brilliance.&lt;/p&gt;

&lt;p&gt;Thanks for reading. Dadah ~ 👋&lt;/p&gt;

</description>
      <category>management</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What is useState in React?</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Tue, 17 Oct 2023 15:00:00 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/what-is-usestate-in-react-47io</link>
      <guid>https://dev.to/mikhaelesa/what-is-usestate-in-react-47io</guid>
      <description>&lt;h2&gt;
  
  
  useState
&lt;/h2&gt;

&lt;p&gt;useState is a React hook used in functional components to manage and update component-specific state. It takes an initial value and returns an array with the current state value and a function to update that state. This allows you to handle dynamic data within your component, such as counters, form inputs, or any changing values.&lt;/p&gt;

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

&lt;p&gt;In my own experience as a React Dev, this hook is one of the hooks that I use the most. It's like we as a React Dev cannot live without it 😆&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use State
&lt;/h2&gt;

&lt;p&gt;useState is one of the simplest hook and a very useful one. Let's see how we can use it in our app&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// const [getter, setter] = useState(optionalInitialState)&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Using the state&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&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;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="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; returns an array where the first item is the getter and the second item is the setter. useState can also take an initial state by passing your desired value as the params. It is a common practice to prefix the setter with &lt;code&gt;set&lt;/code&gt; followed by the state name like the example above.&lt;/p&gt;

&lt;p&gt;Using the state is like using a regular variable. You can just call it inside the component. If you want to use it inside the tags, then you have to wrap it inside a curly bracket.&lt;/p&gt;

&lt;p&gt;Setter is a function to update our state. Updating a state will trigger a re-render to our component and the component's children. We shouldn't mutate our state without using the setter to maintain predictability, immutability, and proper performance. Let's see how we can use it.&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Current&lt;/span&gt; &lt;span class="kr"&gt;number&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we create a click event to set our state to 1. Great it works but, what if we want to keep incrementing it everytime we click the button? Easy, &lt;code&gt;setState&lt;/code&gt; also accepts a callback as a parameter, we can also access the current state through the callback.&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="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="o"&gt;=&amp;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;current&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;current&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Current&lt;/span&gt; &lt;span class="kr"&gt;number&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There we have it! We accessed the current state through the setter and we return the new value for the state. To make it look cleaner and easier to manage, we can put the setter inside a function instead.&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="p"&gt;...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleIncrement&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;current&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;current&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;return&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;handleIncrement&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;Current&lt;/span&gt; &lt;span class="kr"&gt;number&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="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc534jmd9rudb2k14rsqa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc534jmd9rudb2k14rsqa.gif" alt="We did it" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Now that you have learned about useState, try creating some basic app and try to involve useState. If you have any question, feel free to drop a comment and if you liked this article, please give a like and follow me to get an update of this series.&lt;/p&gt;

&lt;p&gt;Dadah~ 👋&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Dependency Inversion Principle in React</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Sat, 14 Oct 2023 14:54:01 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/dependency-inversion-principle-in-react-5287</link>
      <guid>https://dev.to/mikhaelesa/dependency-inversion-principle-in-react-5287</guid>
      <description>&lt;h2&gt;
  
  
  D (Dependency Inversion Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;High-level modules should not depend on low-level modules, but rather both should depend on abstractions&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Dependency Inversion in React involves ensuring that high-level components don't directly depend on low-level components. Instead, both should rely on abstractions, like props or context, to foster flexibility and maintainability. This promotes modularity, simplifies testing, and allows for easier code maintenance.&lt;/p&gt;

&lt;p&gt;Adhering to the Dependency Inversion Principle in React leads to a more scalable architecture with better separation of concerns. It simplifies unit testing by enabling easy mockup of low-level components, enhancing control and precision in testing high-level components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0g2dljtz3o9o2d0ygssi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0g2dljtz3o9o2d0ygssi.gif" alt="Solid" width="220" height="124"&gt;&lt;/a&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateBookForm&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;handleCreateBookForm&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="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;try&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;formData&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&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;https://myapi.com/books&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="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;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCreateBookForm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bookType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component above shows a form for handling create book by rendering a form and send the submitted data to an api.&lt;/p&gt;

&lt;p&gt;Let's imagine if there's another form to edit the book with 100% same ui and differs only from logic. The dependency to the logic of sending data to the API is what makes the form unreusable, so we have to make a component that doesn't depend on a low-level module.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BookForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bookType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have removed the dependency from the form and we can pass the logic through props.&lt;/p&gt;

&lt;p&gt;Now let's use the form!&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateBookForm&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;handleCreateBook&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="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;try&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;formData&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&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;https://myapi.com/books&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BookForm&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCreateBook&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EditBookForm&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;handleEditBook&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="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Another logic&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BookForm&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEditBook&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See now that we have implemented Dependency Inversion Principle, we have a great separation of concerns by abstracting the dependency&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;This is the last part of our &lt;a href="https://dev.to/mikhaelesa/series/24919"&gt;Apply SOLID in React series&lt;/a&gt;. Now that you have a good understanding of SOLID, it's time for you to implement these principles and see how powerful and impactful your codes can be.&lt;/p&gt;

&lt;p&gt;Dadah~ 👋&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Interface Segregation Principle in React</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Sun, 08 Oct 2023 06:01:07 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/interface-segregation-principle-in-react-2501</link>
      <guid>https://dev.to/mikhaelesa/interface-segregation-principle-in-react-2501</guid>
      <description>&lt;p&gt;I (Interface Segregation Principle)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;No code should be forced to depend on methods it does not use&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfuj6aqr0bz8jmw5058z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfuj6aqr0bz8jmw5058z.gif" alt="Taking out the trash" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In React, the Interface Segregation Principle (ISP) emphasizes the importance of creating precise and minimal interfaces for components. It encourages developers to design component interfaces that are tailored to specific needs, avoiding unnecessary bloat. &lt;/p&gt;

&lt;p&gt;This approach results in more modular, maintainable, and reusable code, as components become smaller and focused, promoting better readability and scalability in React applications. ISP encourages cleaner, efficient codebases by advocating for lean and specialized component interfaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfk8pgfdwb86res8bnv7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfk8pgfdwb86res8bnv7.gif" alt="Modular GIF" width="760" height="251"&gt;&lt;/a&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Book image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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;We have a book component which only need few data from the book props which are image, title, and author. By giving it book as a props, we end up giving it more than the component actually need because the book props itself might contain data that the component doesn't need&lt;/p&gt;

&lt;p&gt;To mitigate this problem we can limit the props to only what the component need.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Book image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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;By doing so, we are applying the ISP principle, thus avoiding clients of our component from depending on an interface they are not using. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Let's not stop here since there is 1 principle left to learn in SOLID which I will cover in the next article so stay tuned.&lt;/p&gt;

&lt;p&gt;Dadah~ 👋&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Liskov Substitution Principle in React</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Fri, 06 Oct 2023 06:36:04 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/liskov-substitution-principle-in-react-2p1n</link>
      <guid>https://dev.to/mikhaelesa/liskov-substitution-principle-in-react-2p1n</guid>
      <description>&lt;h2&gt;
  
  
  L (Liskov Substitution Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Objects of a superclass should be replaceable with objects of its subclasses without breaking the application&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;In React, the Liskov Substitution Principle (LSP) underscores the importance of allowing child components to seamlessly replace their parent components while maintaining the same interface and functionality. This enables developers to compose complex user interfaces by substituting components, promoting code reusability and maintainability.&lt;/p&gt;

&lt;p&gt;By adhering to LSP in React, developers create a hierarchy of interchangeable components. This means that base components and their derived counterparts can be swapped without affecting the application's core functionality, simplifying development, enhancing code readability, and facilitating better component behavior understanding. In essence, Liskov Substitution in React encourages the creation of a flexible and cohesive component structure for building robust and maintainable user interfaces.&lt;/p&gt;

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

&lt;p&gt;The implementation is actually not as sophisticated as the explanation. Don't believe me? See for yourself 😉.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DangerButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Danger&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we want to create a &lt;code&gt;DangerButton&lt;/code&gt; component but a button functionality couldn't be replaced by a div so this violates the principle.&lt;/p&gt;

&lt;p&gt;What we should do instead is just return a button like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DangerButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Danger&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks better but it's not enough. We also need to inherit all the functionalities of the button itself.&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IDangerButtonProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ButtonHTMLAttributes&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&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;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;
  &lt;span class="c1"&gt;// Your extra props if you have&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;DangerButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;IDangerButtonProps&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;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;danger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have inherited all of the attributes of the button and we pass the attributes to the new button. This way, any instance of DangerButton can still be used in place of an instance of Button without changing the program’s behavior and complying with the Liskov Substitution Principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Let's not stop here since there are 2 more principles left to learn in SOLID which I will cover in the next article so stay tuned.&lt;/p&gt;

&lt;p&gt;Dadah~ 👋&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Ionic 7 + React Project Setup and Android Studio Live Reload and Debug on Real Device</title>
      <dc:creator>Mikhael Esa</dc:creator>
      <pubDate>Wed, 04 Oct 2023 04:57:25 +0000</pubDate>
      <link>https://dev.to/mikhaelesa/ionic-7-react-project-setup-and-android-studio-live-reload-196f</link>
      <guid>https://dev.to/mikhaelesa/ionic-7-react-project-setup-and-android-studio-live-reload-196f</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Install Ionic CLI
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @ionic/cli 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run this command to scaffold project
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ionic start my-app tabs &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;react &lt;span class="nt"&gt;--capacitor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install android studio latest version. &lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;link here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cd into your ionic project and run these command for android environment&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ionic build
&lt;span class="nv"&gt;$ &lt;/span&gt;ionic cap add android
&lt;span class="nv"&gt;$ &lt;/span&gt;ionic cap open android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will build your app and setup the android environment also open the android studio.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If it's your first time downloading android studio, then it will download the necessary resources first automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the installation is done and nothing is going wrong, then press the play button on the navbar or press &lt;code&gt;Shift + F10&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://download.oracle.com/java/20/latest/jdk-20_windows-x64_bin.zip" rel="noopener noreferrer"&gt;Install JDK 20&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extract JDK&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set environment variable for JAVA_HOME targeting the JDK directory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run this command for live reload on android studio and on browser&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ionic cap run android &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;--external&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run on Real device (Android)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download and install ADB. &lt;a href="https://developer.android.com/tools/releases/platform-tools" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract adb&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an environment Path variable targeting the extracted adb directory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable developer mode on your phone and enable USB debugging. &lt;a href="https://developer.android.com/studio/debug/dev-options" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect your phone to your pc and run adb from command prompt. If there's a popup in your phone asking to allow access from PC, then allow it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally run this command to install debug version of the apk on your phone&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ionic cap run android &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;--external&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ionic</category>
      <category>react</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
