<?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: M. Akbar Nugroho</title>
    <description>The latest articles on DEV Community by M. Akbar Nugroho (@thexdev).</description>
    <link>https://dev.to/thexdev</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%2F308956%2F368d59b9-afc5-4074-909f-0c4cf76e0683.png</url>
      <title>DEV Community: M. Akbar Nugroho</title>
      <link>https://dev.to/thexdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thexdev"/>
    <language>en</language>
    <item>
      <title>✨ 6 website learning gems you should visit!</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Sun, 09 Jun 2024 05:00:00 +0000</pubDate>
      <link>https://dev.to/thexdev/5-website-learning-gems-you-should-visit-2pn5</link>
      <guid>https://dev.to/thexdev/5-website-learning-gems-you-should-visit-2pn5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So you're a software developer? OK that's great. You are able to create application and make 💸💸💸, but have you ever thought for long terms scenarios or do your really aware of it?&lt;/p&gt;

&lt;p&gt;For five years career in software development, creating application is not about to get your job done or delivering the software for launching event. It isn't 🙅‍♂️.&lt;/p&gt;

&lt;p&gt;If you are a good developer, you should aware to the post-development stage of your software...&lt;/p&gt;

&lt;p&gt;🤨: Come on, wheres my "learning gems"?! The title is not about engineering post!&lt;/p&gt;

&lt;p&gt;OK OK I know it's not about engineering post. Fine!&lt;/p&gt;

&lt;p&gt;But...&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%2Fqam933azipo7upyhexo4.jpg" 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%2Fqam933azipo7upyhexo4.jpg" alt="asejrhuasger" width="480" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's enhance our knowledge with these awesome learning materials! From how to architect you application, writing maintainable code, and even knowing how the CPU actually works!&lt;/p&gt;

&lt;p&gt;Btw, let's kudos 🙇‍♂️ to all authors who made these every good learning materials!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.patterns.dev/" rel="noopener noreferrer"&gt;Patterns.dev&lt;/a&gt;
&lt;/h2&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%2Fa2sca89gm5igy58byojn.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%2Fa2sca89gm5igy58byojn.png" alt="Patterns thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Patterns.dev is created by Addy Osmani and Lydia Hallie to help you architect your website to the next level. Patterns.dev will help you to design, rendering, and performance patterns for building powerful web apps with vanilla JavaScript or modern frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://cpu.land/" rel="noopener noreferrer"&gt;Putting the “You” in CPU&lt;/a&gt;
&lt;/h2&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%2Fxqdzvm4uaub99aop9g70.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%2Fxqdzvm4uaub99aop9g70.png" alt="CPU Land thumbnail" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we have the CPU Land!&lt;/p&gt;

&lt;p&gt;Have you ever thought how CPU is actually works under the hood?&lt;/p&gt;

&lt;p&gt;🤨: Why I should think of it if it's already works under the hood?&lt;/p&gt;

&lt;p&gt;Ayo, bro. Come on, are you serious? You won't be replaced by AI, right?&lt;/p&gt;

&lt;p&gt;That's why you should know how CPU execute your program!&lt;/p&gt;

&lt;p&gt;Fortunately this website got you covered. Here you can learn how multiprocessing works, what system calls really are, how computers manage memory with hardware interrupts, and how Linux loads executables.&lt;/p&gt;

&lt;p&gt;All thanks to Lexi Mattick who created this website!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://refactoring.guru/" rel="noopener noreferrer"&gt;Refactoring Guru&lt;/a&gt;
&lt;/h2&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%2Fj2fubawobhmqkyogab86.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%2Fj2fubawobhmqkyogab86.png" alt="Refactoring Guru thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤨: Argh, I don't want to touch this codebase. It's fragile!&lt;/p&gt;

&lt;p&gt;Hey, your wrote this code two years ago...&lt;/p&gt;

&lt;p&gt;🤨: Ah, sorry. I mean yeah... why you're not giving me some solutions, Akbar?&lt;/p&gt;

&lt;p&gt;Me? no man, but Refactoring Guru can help you!&lt;/p&gt;

&lt;p&gt;Alexander Shvets already built cool website to refactor your 💩 codebase. This website will change your perspective of how you can built something that maintainable for long-terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://component.gallery/" rel="noopener noreferrer"&gt;The Component Gallery&lt;/a&gt;
&lt;/h2&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%2Fjqsl23fpudyj78pn8k2f.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%2Fjqsl23fpudyj78pn8k2f.png" alt="Component Gallery thumbnail" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Confused about naming your UI components and how it should looks like? No worries, I often facing this issue. But luckily theres Iain Bean who created The Component Gallery website!&lt;/p&gt;

&lt;p&gt;Here, we are not presented with pre-build UI components rather it gives you what components should looks like and what exactly that for.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://learngitbranching.js.org/" rel="noopener noreferrer"&gt;Learn Git Brancing&lt;/a&gt;
&lt;/h2&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%2Fjbqvf9qc0jszns878xwk.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%2Fjbqvf9qc0jszns878xwk.png" alt="Learn Git Brancing thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have a meme for you, go check it out...&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%2Fwohdbtkh02r6ml2l017w.jpg" 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%2Fwohdbtkh02r6ml2l017w.jpg" alt="khaiusehr" width="600" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, it just meme unless you know how to use Git properly. If you don't, no worries. Just Learn Git Branching!&lt;/p&gt;

&lt;p&gt;Peter Cottle created this website to help you learn Git interactively. You know, because it's easier to understand something if you can visualize it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.12factor.net/" rel="noopener noreferrer"&gt;The Twelve-Factor App&lt;/a&gt;
&lt;/h2&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%2Fojf6okkbrng5meghecwe.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%2Fojf6okkbrng5meghecwe.png" alt="The Twelve-Factor App thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the last, The Twelve-Factor App!&lt;/p&gt;

&lt;p&gt;You'll learn how to build SaaS or simply a service in microservice cluster. Here you are not learn about what technology used, rather the ideology or concept to make your apps portable and easy to deploy anywhere!&lt;/p&gt;

&lt;p&gt;Let's say thanks to Adam Wiggins for his dedication.&lt;/p&gt;

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

&lt;p&gt;Alright, now you already know. Don't give up and keep your learning spirit. In the end it's all just someone's writing, but what makes it valuable is when you apply it and it works.&lt;/p&gt;

&lt;p&gt;If you have any suggestions, don't hesitate to write them in the comments section below!&lt;/p&gt;

&lt;p&gt;See ya!&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%2Fdkbr66wl7xqdixx2n640.jpg" 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%2Fdkbr66wl7xqdixx2n640.jpg" alt="Kocheng hormat" width="465" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>✨ 5 useful productivity apps for every developer!</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Fri, 07 Jun 2024 05:00:00 +0000</pubDate>
      <link>https://dev.to/thexdev/5-useful-productivity-apps-for-every-developer-357b</link>
      <guid>https://dev.to/thexdev/5-useful-productivity-apps-for-every-developer-357b</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When we're working on a project, it's not only about writing and compiling code. You may take a note, schedule your meeting, or even make illustration for your technical documentation.&lt;/p&gt;

&lt;p&gt;Hopefully, theres a tons of software which can help you to achieve those purpose and today I'll share you my 5 most productivity apps I use!&lt;/p&gt;

&lt;p&gt;BTW, this is my personal recommendation. If you have valuable preference, don't hesitate to share with me! 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://notion.so" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;
&lt;/h2&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%2Fptw1ixln64e084yj1alb.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%2Fptw1ixln64e084yj1alb.png" alt="Notion thumbnail" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright! Please welcome, our first place. Notion!&lt;/p&gt;

&lt;p&gt;Who don't know about Notion? All-in-one, feature rich note taking apps where you can do almost all note taking activity. From making simple note even more advanced one.&lt;/p&gt;

&lt;p&gt;Notion allows you to organise your notes, documentation, timeline or even calendar. A perfect apps for you who wont use many apps to make something. Notion includes it in one place!&lt;/p&gt;

&lt;p&gt;🤔: I use Linux, does it support for Linux?&lt;/p&gt;

&lt;p&gt;Don't be worry you've covered. Even though Notion doesn't have official apps for Linux, but luckily there &lt;a href="https://snapcraft.io/notion-snap-reborn" rel="noopener noreferrer"&gt;unofficial Notion distribution on Snapcraft&lt;/a&gt;. So, as long as you have Snap installed then you are ready to install Notion!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://excalidraw.com" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt;
&lt;/h2&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%2F5cqnpgr2aqe5qm0oue50.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%2F5cqnpgr2aqe5qm0oue50.png" alt="Excalidraw thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, you like drawing your idea? Clarify your argument by illustrate it? I think Excalidraw is perfect match for you!&lt;/p&gt;

&lt;p&gt;I also use it for my daily, like this post below.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/thexdev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F308956%2F368d59b9-afc5-4074-909f-0c4cf76e0683.png" alt="thexdev"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/thexdev/slowed-by-region-24d2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Slowed by Region&lt;/h2&gt;
      &lt;h3&gt;M. Akbar Nugroho ・ Jun 3 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#remix&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vercel&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Even better, Excalidraw also has many libraries that you can use for free!&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://libraries.excalidraw.com/?theme=light&amp;amp;amp%3Bsort=default" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fexcalidraw.com%2Fog-image.png" height="" class="m-0" width=""&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://libraries.excalidraw.com/?theme=light&amp;amp;amp%3Bsort=default" rel="noopener noreferrer" class="c-link"&gt;
            Excalidraw Libraries
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A directory of public libraries that you can easily add to Excalidraw.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flibraries.excalidraw.com%2Ffavicon.ico" width="256" height="256"&gt;
          libraries.excalidraw.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;🤔: I want to use it on my machine&lt;/p&gt;

&lt;p&gt;Ofc you can! Excalidraw is open source project hosted on GitHub. You can clone and run it on your local machine or even your own server.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/excalidraw" rel="noopener noreferrer"&gt;
        excalidraw
      &lt;/a&gt; / &lt;a href="https://github.com/excalidraw/excalidraw" rel="noopener noreferrer"&gt;
        excalidraw
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Virtual whiteboard for sketching hand-drawn like diagrams
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;a href="https://excalidraw.com/" rel="nofollow noopener noreferrer"&gt;
  
    
    &lt;img alt="Excalidraw" src="https://camo.githubusercontent.com/998e67de729ddc7a96857f3ad11075481ee1ea59e6c5e79c6b13886013cce97b/68747470733a2f2f657863616c69647261772e6e7963332e63646e2e6469676974616c6f6365616e7370616365732e636f6d2f6769746875622f657863616c69647261775f6769746875625f636f7665725f322e706e67"&gt;
  
&lt;/a&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;
  &lt;a href="https://excalidraw.com" rel="nofollow noopener noreferrer"&gt;Excalidraw Editor&lt;/a&gt; |
  &lt;a href="https://plus.excalidraw.com/blog" rel="nofollow noopener noreferrer"&gt;Blog&lt;/a&gt; |
  &lt;a href="https://docs.excalidraw.com" rel="nofollow noopener noreferrer"&gt;Documentation&lt;/a&gt; |
  &lt;a href="https://plus.excalidraw.com" rel="nofollow noopener noreferrer"&gt;Excalidraw+&lt;/a&gt;
&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;
    An open source virtual hand-drawn style whiteboard. &lt;br&gt;
    Collaborative and end-to-end encrypted. &lt;br&gt;
  &lt;br&gt;
  &lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;
  &lt;a href="https://github.com/excalidraw/excalidraw/blob/master/LICENSE" rel="noopener noreferrer"&gt;
    &lt;img alt="Excalidraw is released under the MIT license." src="https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/@excalidraw/excalidraw" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="npm downloads/month" src="https://camo.githubusercontent.com/b888038a3f43d195f22378d9e805a780cf8ae92b3a21170cf3b9a6d49b646c90/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f40657863616c69647261772f657863616c6964726177"&gt;&lt;/a&gt;
  &lt;a href="https://docs.excalidraw.com/docs/introduction/contributing" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="PRs welcome!" src="https://camo.githubusercontent.com/7d9ed3c8f22eceb1711573169b1390cc0b1194467340dc815205060c162b5309/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e7376673f7374796c653d666c6174"&gt;&lt;/a&gt;
  &lt;a href="https://discord.gg/UexuTaE" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="Chat on Discord" src="https://camo.githubusercontent.com/a41f6a4ded761f96348dcbb5cccdd105782b31cbc0cebc245616fb6adc6ed90d/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3732333637323433303734343137343638323f636f6c6f723d373338616436266c6162656c3d436861742532306f6e253230446973636f7264266c6f676f3d646973636f7264266c6f676f436f6c6f723d6666666666662677696467653d66616c7365"&gt;&lt;/a&gt;
  &lt;a href="https://deepwiki.com/excalidraw/excalidraw" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="Ask DeepWiki" src="https://camo.githubusercontent.com/0f5ae213ac378635adeb5d7f13cef055ad2f7d9a47b36de7b1c67dbe09f609ca/68747470733a2f2f6465657077696b692e636f6d2f62616467652e737667"&gt;&lt;/a&gt;
  &lt;a href="https://twitter.com/excalidraw" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="Follow Excalidraw on Twitter" src="https://camo.githubusercontent.com/601234ddc1c94ae90113c962cbae8f570910de0a8706705d1a27897cd74e47ad/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f657863616c69647261772e7376673f6c6162656c3d666f6c6c6f772b40657863616c6964726177267374796c653d736f6369616c266c6f676f3d74776974746572"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div&gt;
    &lt;a href="https://excalidraw.com" rel="nofollow noopener noreferrer"&gt;
      &lt;img src="https://camo.githubusercontent.com/1be1106db66a9fbbe2a19cc027266ff647ecb7269d542e0712ff36d4a25c294a/68747470733a2f2f657863616c69647261772e6e7963332e63646e2e6469676974616c6f6365616e7370616365732e636f6d2f67697468756225324670726f647563745f73686f77636173652e706e67" alt="Product showcase"&gt;
    &lt;/a&gt;
    
      &lt;p&gt;
        Create beautiful hand-drawn like diagrams, wireframes, or whatever you like.
      &lt;/p&gt;
    
  
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;The Excalidraw editor (npm package) supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💯 Free &amp;amp; open-source.&lt;/li&gt;
&lt;li&gt;🎨 Infinite, canvas-based whiteboard.&lt;/li&gt;
&lt;li&gt;✍️ Hand-drawn like style.&lt;/li&gt;
&lt;li&gt;🌓 Dark mode.&lt;/li&gt;
&lt;li&gt;🏗️ Customizable.&lt;/li&gt;
&lt;li&gt;📷 Image support.&lt;/li&gt;
&lt;li&gt;😀 Shape libraries support.&lt;/li&gt;
&lt;li&gt;🌐 Localization (i18n) support.&lt;/li&gt;
&lt;li&gt;🖼️ Export to PNG, SVG &amp;amp; clipboard.&lt;/li&gt;
&lt;li&gt;💾 Open format - export drawings as an &lt;code&gt;.excalidraw&lt;/code&gt; json file.&lt;/li&gt;
&lt;li&gt;⚒️ Wide range of tools - rectangle, circle, diamond, arrow, line, free-draw, eraser...&lt;/li&gt;
&lt;li&gt;➡️ Arrow-binding &amp;amp; labeled arrows.&lt;/li&gt;
&lt;li&gt;🔙 Undo / Redo.&lt;/li&gt;
&lt;li&gt;🔍 Zoom and panning support.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Excalidraw.com&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;The app hosted at &lt;a href="https://excalidraw.com" rel="nofollow noopener noreferrer"&gt;excalidraw.com&lt;/a&gt; is a minimal showcase of what you can build with Excalidraw. Its &lt;a href="https://github.com/excalidraw/excalidraw/tree/master/excalidraw-app" rel="noopener noreferrer"&gt;source code&lt;/a&gt; is part of this repository as well, and the app features:&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;📡 PWA support (works offline).&lt;/li&gt;

&lt;li&gt;🤼 Real-time collaboration.&lt;/li&gt;

&lt;li&gt;🔒 End-to-end…&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/excalidraw/excalidraw" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;
&lt;/h2&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%2F8djxtmke7agfbxuaa4mn.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%2F8djxtmke7agfbxuaa4mn.png" alt="Postman thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Postman is not only about HTTP Agent. It's more than that! Postman is collaboration platform that bridge back-end, front-end, and QA in one place.&lt;/p&gt;

&lt;p&gt;It makes easy to document your APIs endpoint and share it to everyone. Postman also gives you ability to make API mock and much more. And the latest version of Postman is also supports gRPC 😍.&lt;/p&gt;

&lt;p&gt;So, when your front-end or QA ask you about APIs endpoint. Don't be afraid. Just send them the Postman Collection and you can continue your work 😁.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.sublimemerge.com/" rel="noopener noreferrer"&gt;Sublime Merge&lt;/a&gt;
&lt;/h2&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%2Fnq0y6f6f6vlmf3rd2ifo.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%2Fnq0y6f6f6vlmf3rd2ifo.png" alt="Sublime Merge thumbnail" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My very loved Git GUI apps! Simple, lightweight, and very fast! No more working with CLI 😁&lt;/p&gt;

&lt;p&gt;Sublime Merge offers you to use Git in a simple way. From commit, manage your branch, even cherry picking!&lt;/p&gt;

&lt;p&gt;It's so powerful to work with Git, but very light. A perfect match for you who want minimalist, on point, and powerful Git GUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://habitica.com" rel="noopener noreferrer"&gt;Habitica&lt;/a&gt;
&lt;/h2&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%2Fo55voprz4644ncwk1hld.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%2Fo55voprz4644ncwk1hld.png" alt="Habitica thumbnail" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's be honest, working is one of most boring activity we like (because it generates money for use hohoho). But, how about to gamify it? I think it's more fun, tho? If so, Habitica is the right choice!&lt;/p&gt;

&lt;p&gt;Habitica let's you gamify your life like RPG game. You doing something, getting points, and receive reward!&lt;/p&gt;

&lt;p&gt;It's better than doing something, finish it, and go to sleep right? 😁&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;For me, those apps is very useful for my daily use. From taking notes, documenting project, collaboration activity, and even for fun.&lt;/p&gt;

&lt;p&gt;I prefer minimal and not bloated apps in my computer which focus to all-in-one features. Because I want to make my self productive and make my work easy.&lt;/p&gt;

&lt;p&gt;Sometimes, too much apps could distract and lead you to confusion. Choosing a right apps is tricky because everyone has their preferences. But, if I could, I want to suggest you to choose productivity apps that simple and has features that everyone easy to access.&lt;/p&gt;

&lt;p&gt;If you work in personal, all choice is yours! But, if you work on team which requires you to collaborate each other, you can give it a try my list above!&lt;/p&gt;

&lt;p&gt;Btw, at the end. Your goals is to make your job done. And all preferences is yours. If you have any suggestion don't hesitate to comment below!&lt;/p&gt;

&lt;p&gt;Thanks for coming. See ya!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
      <category>codenewbie</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>✨ 10 useful webdev insight &amp; learning resources!</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Wed, 05 Jun 2024 12:58:38 +0000</pubDate>
      <link>https://dev.to/thexdev/10-useful-webdev-insight-learning-resources-eoe</link>
      <guid>https://dev.to/thexdev/10-useful-webdev-insight-learning-resources-eoe</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post, I'll give you ten useful resources specific for web development.&lt;/p&gt;

&lt;p&gt;All provided resources below are not definitely (step-by-step) tutorial for web dev. Instead, it's a guide to build secure, accessible and performant modern web application.&lt;/p&gt;

&lt;p&gt;The main subjects of this post are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web accessibilty (WAI-ARIA)&lt;/li&gt;
&lt;li&gt;Web APIs&lt;/li&gt;
&lt;li&gt;Progressive Web Apps&lt;/li&gt;
&lt;li&gt;Web Security&lt;/li&gt;
&lt;li&gt;SEO (included Structured Data)&lt;/li&gt;
&lt;li&gt;Design Patterns&lt;/li&gt;
&lt;li&gt;Performant Measurement&lt;/li&gt;
&lt;li&gt;Tools &amp;amp; Debugging Techniques&lt;/li&gt;
&lt;li&gt;HTML &amp;amp; CSS Syntax References&lt;/li&gt;
&lt;li&gt;And many more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on the covered subjects, I hope you already learned the basic of web development. If not, don't worry. You can read these all for your reference tomorrow 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&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%2Fq9952k2yuv6a2sfg33x3.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%2Fq9952k2yuv6a2sfg33x3.png" alt="webdev" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://web.dev/" rel="noopener noreferrer"&gt;WEB.DEV&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Web.dev is a guidance from Chrome Developer Relations. They want to help you build beautiful, accessible, fast, and secure websites that work cross-browser, and for all of your users.&lt;/p&gt;

&lt;p&gt;This site is our home for content to help you on that journey, written by members of the Chrome team, and external experts.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blog&lt;/strong&gt;. Latest news, updates, and stories for developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn&lt;/strong&gt;. An industry expert has written each course, helped by members of the Chrome team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore&lt;/strong&gt;. Structured learning paths to discover everything you need to know about building for the modern web.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case Studies&lt;/strong&gt;. Learn why and how other developers have used the web to create amazing web experiences for their users.&lt;/li&gt;
&lt;/ul&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%2Flmg9z840c1em6psew5x5.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%2Flmg9z840c1em6psew5x5.png" alt="MDN" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://developer.mozilla.org/en-US/" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;MDN Web Docs is an open-source, collaborative project documenting Web platform technologies, including CSS, HTML, JavaScript, and Web APIs.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;References. The docs for web APIs, accessibility, security, performance, etc.&lt;/li&gt;
&lt;li&gt;Guides. Step-by-step learn web development. The aim of this area of MDN is not to take you from "beginner" to "expert" but to take you from "beginner" to "comfortable".&lt;/li&gt;
&lt;/ul&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%2F69sooyzjc7u8e52dg4yb.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%2F69sooyzjc7u8e52dg4yb.png" alt="Chrome Developer" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://developer.chrome.com/en/" rel="noopener noreferrer"&gt;Chrome Developer&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The Chrome's official site to help you build Extensions, publish on the Chrome Web Store, optimize your website, and more.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docs&lt;/strong&gt;. The documentation of Chrome's tools &amp;amp; library, extension &amp;amp; web store, architecture, and infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog&lt;/strong&gt;. Latest update of Chrome and web technologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Articles&lt;/strong&gt;. Latest research of Chrome's team and other insightful write.&lt;/li&gt;
&lt;/ul&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%2Fed7otuijehedw4wl2oem.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%2Fed7otuijehedw4wl2oem.png" alt="Google Search Central" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://developers.google.com/search" rel="noopener noreferrer"&gt;Google Search Central&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Google Search Central is here to help the right people view your content with resources to make your website discoverable to Google Search.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SEO fundamentals.&lt;/li&gt;
&lt;li&gt;Crawling and indexing.&lt;/li&gt;
&lt;li&gt;Ranking and search appearance.&lt;/li&gt;
&lt;li&gt;Site-specific guides.&lt;/li&gt;
&lt;/ul&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%2Fjolwxr725uur4fq00qv6.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%2Fjolwxr725uur4fq00qv6.png" alt="CSS Tricks" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://css-tricks.com/" rel="noopener noreferrer"&gt;CSS Tricks&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;CSS-Tricks is a renowned online platform dedicated to everything related to Cascading Style Sheets (CSS) and front-end web development. Established by Chris Coyier in 2007, CSS-Tricks has evolved into a comprehensive resource hub for web designers and developers seeking to enhance their skills, stay updated with the latest trends, and find solutions to their CSS-related queries.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Articles and Tutorials.&lt;/strong&gt; CSS-Tricks offers a plethora of articles and tutorials covering a wide range of topics, from basic CSS techniques to advanced front-end development concepts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Snippets.&lt;/strong&gt; Developers can find ready-to-use code examples for common UI patterns, layout designs, and CSS tricks, saving them time and effort in their projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Almanac.&lt;/strong&gt; The CSS-Tricks Almanac serves as a comprehensive reference guide for CSS properties, selectors, functions, and other essential concepts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;News and Updates&lt;/strong&gt;. CSS-Tricks keeps its audience informed about the latest trends, tools, and updates in the world of front-end development through regular news articles and curated content.&lt;/li&gt;
&lt;/ul&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%2Fqv2307o3tb869lrjdbp8.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%2Fqv2307o3tb869lrjdbp8.png" alt="JS Info Thumbnail" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://javascript.info/" rel="noopener noreferrer"&gt;JavaScript Info&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Your gateway to mastering the art of JavaScript programming! Dive into the world of JavaScript and unlock its full potential with our comprehensive resources and guidance.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exploring Tutorials.&lt;/strong&gt; Embark on a journey through our extensive collection of tutorials, meticulously crafted to guide you through the intricacies of JavaScript programming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consulting the Reference Materials.&lt;/strong&gt; Comprehensive reference materials to deepen your understanding of JavaScript syntax, methods, and objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exploring ES6+ Features.&lt;/strong&gt; Stay up-to-date with the latest advancements in JavaScript by exploring ES6+ features such as arrow functions, template literals, and destructuring assignments.&lt;/li&gt;
&lt;/ul&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%2F4o13bmihp88mlgby6675.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%2F4o13bmihp88mlgby6675.png" alt="HTML Reference IO" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://htmlreference.io/" rel="noopener noreferrer"&gt;HTML Reference&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Your ultimate guide to mastering HTML and harnessing its full potential in web development! HTMLReference.io is a comprehensive online resource dedicated to providing detailed documentation, examples, and best practices for HTML elements and attributes.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exploring HTML5 Features.&lt;/strong&gt; Stay ahead of the curve with our coverage of HTML5 features and enhancements. From semantic elements like "header" and "footer" to multimedia elements like "video" and "audio".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understanding Attributes.&lt;/strong&gt; Unravel the mysteries of HTML attributes with our in-depth explanations and usage examples. From common attributes like "id" and "class" to more advanced attributes like "data-" and "aria-".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick Reference Guides.&lt;/strong&gt; Access quick reference guides for common HTML tasks and scenarios, such as creating forms, embedding multimedia content, and structuring web pages.&lt;/li&gt;
&lt;/ul&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%2Fhalypxefo0zctuvbg8h5.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%2Fhalypxefo0zctuvbg8h5.png" alt="Patterns Thumbnail" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.patterns.dev/" rel="noopener noreferrer"&gt;Patterns&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The brainchild of the legendary &lt;a href="https://addyosmani.com/" rel="noopener noreferrer"&gt;Addy Osmani&lt;/a&gt;, where cutting-edge design meets practical implementation in the world of web development! Patterns is a premier online resource dedicated to showcasing innovative design patterns, architectural principles, and best practices curated by Addy Osmani and his team of experts.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exploring Design Patterns.&lt;/strong&gt; Delve into the world of design patterns with Patterns, where you'll discover a treasure trove of tried-and-tested solutions to common design challenges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural Principles.&lt;/strong&gt; Unlock the secrets of scalable, maintainable architecture with our in-depth exploration of architectural principles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices and Guidelines.&lt;/strong&gt; Navigate the complexities of modern web development with confidence, armed with our collection of best practices and guidelines.&lt;/li&gt;
&lt;/ul&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%2Fixbioa9xjgzh0prpm1t8.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%2Fixbioa9xjgzh0prpm1t8.png" alt="Can I use Thumbnail" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://caniuse.com/" rel="noopener noreferrer"&gt;Can I use...&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Your trusty companion in the ever-evolving landscape of web development compatibility! "Can I Use" is a renowned online tool that provides comprehensive information about web browser support for HTML, CSS, JavaScript features, and more.&lt;/p&gt;

&lt;p&gt;What's included?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser Compatibility Made Easy.&lt;/strong&gt; Navigating browser compatibility can be a daunting task, but fear not! "Can I Use" simplifies the process by offering clear and concise information about which web technologies are supported by various browsers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensive Database of Features.&lt;/strong&gt; Explore our extensive database of web features, including HTML elements, CSS properties, JavaScript APIs, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical Data and Trends.&lt;/strong&gt; Track the evolution of web browser support over time with our historical data and trends.&lt;/li&gt;
&lt;/ul&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%2Fm4egk5i3kb8g0ki724mb.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%2Fm4egk5i3kb8g0ki724mb.png" alt="Figma Community" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://figma.com/community" rel="noopener noreferrer"&gt;Figma Community&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Where creativity knows no bounds and collaboration thrives! The Figma Community is an innovative platform that brings together designers, creators, and design enthusiasts from around the world to share, discover, and collaborate on design projects using Figma's powerful tools.&lt;/p&gt;

&lt;p&gt;What's included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explore and Discover.&lt;/strong&gt; Discover a treasure trove of design resources, including UI kits, icon sets, illustrations, and more, created by talented designers within the Figma Community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay Inspired.&lt;/strong&gt; Stay inspired and up-to-date with the latest design trends, techniques, and industry insights by following your favorite creators and joining design communities within Figma Community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contribute to Open Source.&lt;/strong&gt; Contribute to the world of open-source design by sharing your design assets, components, and templates with the broader design community.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In conclusion, these ten web development resources offer a diverse range of tools and opportunities for designers and developers to enhance their skills, find inspiration, and collaborate with others in the industry.&lt;/p&gt;

&lt;p&gt;From vibrant communities to comprehensive design libraries, these platforms empower creativity, foster collaboration, and provide invaluable insights for individuals at every stage of their web development journey.&lt;/p&gt;

&lt;p&gt;Whether you're seeking to showcase your work, explore new techniques, or contribute to the global design community, these resources offer a wealth of knowledge and learning opportunities to help you succeed in the ever-evolving world of web development.&lt;/p&gt;

&lt;p&gt;See ya!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Slowed by Region</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Mon, 03 Jun 2024 08:25:46 +0000</pubDate>
      <link>https://dev.to/thexdev/slowed-by-region-24d2</link>
      <guid>https://dev.to/thexdev/slowed-by-region-24d2</guid>
      <description>&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;I just publish my product &lt;a href="https://etalase.store" rel="noopener noreferrer"&gt;Etalase&lt;/a&gt; that built with Remix and Hono. The problem comes from the Remix side which hosted on Vercel. For Hono, I use Deno as the runtime engine and hosted it on Deno Deploy combined with Supabase Database.&lt;/p&gt;

&lt;p&gt;My Remix page is rendered ~500ms approximately when I back to previous page. For example, from home to products then back again to home. As my inspection, the problem comes from my Vercel region set to Washington while my Supabase and Deno are set to Singapore.&lt;/p&gt;

&lt;p&gt;So, setting region for each Platform you use to same region should resolve this issue 😁.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crab, why so slow?
&lt;/h2&gt;

&lt;p&gt;I'm asking my self why my page get slower after adding some API calls into loader function. It approximately ~500ms. It's very slow for zero users (for now 😅). Is that because my API slow? nope, I tested it and it fast!&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%2F01sdy8uzyz9iwxfbwpcz.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%2F01sdy8uzyz9iwxfbwpcz.png" alt="IDK what meme is this" width="752" height="750"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does my loader not optimized yet? Yeah, it does, but this platform still zero users 😭. Such a beautiful realize...&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming tears from "I'm OK" promises
&lt;/h2&gt;

&lt;p&gt;"OK FINE! Let's tune this" I said it to my self.&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%2F0yp6b087znypdxijvjg2.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%2F0yp6b087znypdxijvjg2.png" alt="Yeah shit" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all" rel="noopener noreferrer"&gt;Promise.all()&lt;/a&gt; API to aggregate all promises together. I thought the loader slow because the promises running sequentially. After doing that, the result? it does not change anything 🙂.&lt;/p&gt;

&lt;p&gt;"How about to streaming this?" I'm literally said it to my self.&lt;/p&gt;

&lt;p&gt;Btw, Remix has &lt;a href="https://remix.run/docs/en/main/guides/streaming" rel="noopener noreferrer"&gt;streaming&lt;/a&gt; ability to stream your data into UI. As soon as your first chunk of data received by loader function it stream into the UI.&lt;/p&gt;

&lt;p&gt;And after doing this 🥁🥁🥁...&lt;/p&gt;

&lt;p&gt;It also does not change anything 🙂.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's &lt;del&gt;drown&lt;/del&gt; draw
&lt;/h2&gt;

&lt;p&gt;Enough for trying, let's analyzing.&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%2F8myx1johdglb1c8cqd1d.jpg" 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%2F8myx1johdglb1c8cqd1d.jpg" alt="Senku hahaha" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I define the problem. it's SLOW. My expectation is FAST. I've tried two different method: Promise.all and Streaming and it fails.&lt;/p&gt;

&lt;p&gt;Now let's make some scenario.&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%2Fcrsm75wt9134wqfvl0wj.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%2Fcrsm75wt9134wqfvl0wj.png" alt="yyy" width="745" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And focus to the problem.&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%2F0yj4yqcyfyh07lvdi36m.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%2F0yj4yqcyfyh07lvdi36m.png" alt="zzz" width="558" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;fetch&lt;/a&gt; to connect with my API that returns promise and make it parallel using &lt;code&gt;Promise.all()&lt;/code&gt;. Since fetch is using HTTP based communication this can have two main problems: slow request times or slow response times.&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%2F4zrahzcxbj9rtetpsval.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%2F4zrahzcxbj9rtetpsval.png" alt="http" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, based on my scenario above I have no problem for Browser and Postman. So what happen? OK Let's figure out what actually make HTTP based communication get slowed specially on the network side because I know my connection is good and data being transferred is small.&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%2F5smvyihg643k6pppzwub.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%2F5smvyihg643k6pppzwub.png" alt="adf" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh, wait. Latency? I though I've got some light of God 😭&lt;/p&gt;

&lt;p&gt;You know? The actual response times for your server is &lt;code&gt;time (ms) = latency + server request or response times&lt;/code&gt;. As I remember the major problem for latency is a distance between client and the server itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Triggered
&lt;/h2&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%2Fb4savqgxbpvthruk5tl7.jpg" 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%2Fb4savqgxbpvthruk5tl7.jpg" alt="adfasdf" width="800" height="734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait 🤨 (100x)...&lt;/p&gt;

&lt;p&gt;"What the default region of my Vercel serverless function?", I said.&lt;/p&gt;

&lt;p&gt;I immediately open my Vercel Functions settings to check the region. And you know, it's "Washington, D.C., USA ( iad1 )" by default.&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%2Frsa7waab7erkqcldljdp.jpg" 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%2Frsa7waab7erkqcldljdp.jpg" alt="kliuyu" width="721" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📖 Here's the reference for you&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://vercel.com/docs/functions/configuring-functions/region" rel="noopener noreferrer"&gt;Configuring Regions for Vercel Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vercel.com/docs/frameworks/remix" rel="noopener noreferrer"&gt;Remix on Vercel&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;It took my three hours to debug. Thanks, btw 🙂.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming tears (again, but really)
&lt;/h2&gt;

&lt;p&gt;After realized that problem I change my serverless function to Singapore and apply it.&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%2Fz1ig3wxxrpsf3i882xwc.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%2Fz1ig3wxxrpsf3i882xwc.png" alt="sihauiserh" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, I re-check all services are located to Singapore. And the final test is... "fast". I'm very happy about it and take some break to make a coffee.&lt;/p&gt;

&lt;p&gt;To summarize, I give you some checklist if your Remix function slow even thought it isn't hosted on Vercel.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;Promise.all()&lt;/code&gt;. If it can't help, use...&lt;/li&gt;
&lt;li&gt;Remix &lt;code&gt;Streaming&lt;/code&gt;. Or even worst...&lt;/li&gt;
&lt;li&gt;Check your client-server latency issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See ya!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>remix</category>
      <category>vercel</category>
    </item>
    <item>
      <title>✨ 5 websites to get free programming e-book!</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Wed, 22 Mar 2023 09:19:15 +0000</pubDate>
      <link>https://dev.to/thexdev/5-websites-to-get-free-programming-e-book-115g</link>
      <guid>https://dev.to/thexdev/5-websites-to-get-free-programming-e-book-115g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is five websites that provide e-book for learning programming language, framework, platform, etc for free.&lt;/p&gt;

&lt;p&gt;The files are downloadable to PDF and licensed (mostly) under common creative, MIT and other public licenses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📌 NGINX Library
&lt;/h3&gt;

&lt;p&gt;NGINX Library offers you many free (included O'Relly) e-books that you can download on their official website.&lt;/p&gt;

&lt;p&gt;Those books talk about cloud computing such as DevOps, DevSec, Kubernetes, Microservice, etc.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;&lt;a href="https://www.nginx.com/resources/library/" rel="noopener noreferrer"&gt;🔗 Access Link&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📢 &lt;strong&gt;UPDATE!&lt;/strong&gt;&lt;br&gt;
Since &lt;a href="https://www.f5.com/company/news/press-releases/f5-completes-acquisition-of-nginx" rel="noopener noreferrer"&gt;NGINX already acquired by F5&lt;/a&gt;, the provided link above is unavailable somehow. Maybe it's taken down or on progress, but as a change I'll give you one website from Packt below :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📌 Packt Free Learning
&lt;/h3&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%2Fw5t4m369kwug3fw735kf.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%2Fw5t4m369kwug3fw735kf.png" alt="Packt Free Learning wesbite thubmnail" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A new free programming tutorial book every day! Develop new tech skills and knowledge with Packt Publishing's daily free learning giveaway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.packtpub.com/free-learning/" rel="noopener noreferrer"&gt;🔗 Access link&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  📌 Programming Notes for Professionals
&lt;/h3&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%2F7xinq93t9a998ej8b938.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%2F7xinq93t9a998ej8b938.png" alt="Programming Notes for Professionals website thumbnail" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These books are not a tutorial ebook, but it's kinda note for experienced developer about tools and programming language.&lt;/p&gt;

&lt;p&gt;Some of their books are JavaScript, Kotlin, React, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://goalkicker.com/" rel="noopener noreferrer"&gt;🔗 Access Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📌 Ebook Foundation
&lt;/h3&gt;

&lt;p&gt;Free Programming Books is a list of over 4,000 free programming books, 2,000 free courses and many other free programming resources, maintained collaboratively as a repository on Github. With lists in 43 spoken languages, it has helped countless programmers around the world acquire and improve their programming abilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ebookfoundation.org/f-p-b.html" rel="noopener noreferrer"&gt;🔗 Access Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📌 Free Computer Books
&lt;/h3&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%2Fxs5mr9vn7sggmdknkslx.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%2Fxs5mr9vn7sggmdknkslx.png" alt="Free Computer Books website thumbnail" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This site is a directory of Hyperlinks to free ebooks, tutorials, and lecture notes, etc, all over the world. It is basically a free service to the communities with the focus on Information Technologies, Computer Science, Mathematics, etc.&lt;/p&gt;

&lt;p&gt;Therefore, all the items (books, lecture notes, etc.) listed in this site are just Hyperlinks to other web pages all over the world (same as search results in Google). That includes, but not limited to, ebooks, lecture notes, and tutorials, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freecomputerbooks.com" rel="noopener noreferrer"&gt;🔗 Access Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📌 SoftUni Free Books
&lt;/h3&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%2Fembr2aoc0093q0vvio16.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%2Fembr2aoc0093q0vvio16.png" alt="SoftUni Free Books website thumbnail" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This website offers basics programming language like Java, Python, JavaScript, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://softuni.org/learn/resources/free-programming-books/" rel="noopener noreferrer"&gt;🔗 Access Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it. I hope it help you. Thanks for reading!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/thexdev" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>programming</category>
      <category>community</category>
    </item>
    <item>
      <title>The new React docs</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Fri, 17 Mar 2023 16:38:20 +0000</pubDate>
      <link>https://dev.to/thexdev/the-new-react-docs-3e7</link>
      <guid>https://dev.to/thexdev/the-new-react-docs-3e7</guid>
      <description>&lt;p&gt;Congratulations for all React team! 🎉&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636441676506906626-669" src="https://platform.twitter.com/embed/Tweet.html?id=1636441676506906626"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636441676506906626-669');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636441676506906626&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Today, the new React homepage and documentation just released and I'm very happy about it. It's a long journey story.&lt;/p&gt;

&lt;p&gt;This post will tell you about the updates and guide you through the website.&lt;/p&gt;

&lt;p&gt;Are you ready?&lt;/p&gt;

&lt;p&gt;I'm very excited about this. Let's go! 😁&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Domain
&lt;/h2&gt;

&lt;p&gt;The new documentation is moved to &lt;a href="https://react.dev" rel="noopener noreferrer"&gt;react.dev&lt;/a&gt;. Don't worry about the old one. We can still access it from &lt;a href="https://legacy.reactjs.org" rel="noopener noreferrer"&gt;legacy.reactjs.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you previously put the old website into your post or article, it will redirect the link to the new site to void breaking changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Navbar
&lt;/h2&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%2F4isepajwoszw3euk1w1e.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%2F4isepajwoszw3euk1w1e.png" alt="New React sites navbar" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new navbar looks content-first now. Long searchbar is the first thing you should see. And you are free to search anything you want.&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%2Fg3vyyz183viaztjvkr1v.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%2Fg3vyyz183viaztjvkr1v.png" alt="Open modal" width="800" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The opened modal is much larger. Gives you better experience compared to the previous version.&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%2Fvs8p52hgeydfzcjih4yi.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%2Fvs8p52hgeydfzcjih4yi.png" alt="Previous version searchbar" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Guest what the best part? Yes, The theme switch!&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%2Fvcbsz0e7sux9ai1udykv.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%2Fvcbsz0e7sux9ai1udykv.gif" alt="Them switch" width="760" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, the language menu is missing now... I think it's on progress? 🤷‍♂️. No worries...&lt;/p&gt;




&lt;p&gt;And the GitHub link redirects you to the release page instead of the README one.&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%2Fx7tgr7wh4s8rxv2xotla.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%2Fx7tgr7wh4s8rxv2xotla.gif" alt="Redirect to release" width="760" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Learn Section
&lt;/h2&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%2F1p2srgv7yijoczuex4ih.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%2F1p2srgv7yijoczuex4ih.png" alt="Learn section sidebar" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the most highlighted part. I'm very happy for this updates.&lt;/p&gt;

&lt;p&gt;I was following the React community since 2019. Many of my friends and other people struggle reading the docs because it's not a beginner friendly and feels very technical 😅.&lt;/p&gt;

&lt;p&gt;The React team heard those voices. They restructured the Quick Start and transform it. Entirely!&lt;/p&gt;

&lt;p&gt;Now, we have more example codes...&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%2Fcgl535gea6fdj803nene.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%2Fcgl535gea6fdj803nene.png" alt="Example codes" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and sandbox to play!&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%2Fqmz0klkmxtjmsshzjpav.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%2Fqmz0klkmxtjmsshzjpav.png" alt="Sandbox" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The choice of words is also very easy to understand. If you read the Quick Start from start 'til the end, you should feeling it guides you step-by-step.&lt;/p&gt;

&lt;p&gt;Plus...&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%2Fsjo32jmb8gu3ya53jdhv.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%2Fsjo32jmb8gu3ya53jdhv.png" alt="Illustration" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...more illustration to help you understand better! 😍&lt;/p&gt;




&lt;p&gt;If you need more practical way for learning React, you can go to &lt;strong&gt;Tutorial: Tic-Tac-Toe&lt;/strong&gt;. It will gives you many insights about how you can use React to build your UI.&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%2Fa63nqwo1z3t35d9cxokh.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%2Fa63nqwo1z3t35d9cxokh.png" alt="Tutorial: Tic-Tac-Toe" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a step-by-step and detailed tutorial. Sandbox, illustration, and codes is provided. Awesome! 😁&lt;/p&gt;




&lt;p&gt;For you, if you want to explore more about React, you can read &lt;strong&gt;Describing the UI&lt;/strong&gt;, &lt;strong&gt;Adding Interactivity&lt;/strong&gt;, &lt;strong&gt;Managing State&lt;/strong&gt;, and &lt;strong&gt;Escape Hatches&lt;/strong&gt; topics.&lt;/p&gt;

&lt;p&gt;React team is also adding difficulty badge to give you more attention to the topic.&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%2Fu3k39vvyc38st3b124ox.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%2Fu3k39vvyc38st3b124ox.png" alt="Intermediate" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reference Section
&lt;/h2&gt;

&lt;p&gt;This sections contains all of React built-in APIs. The React team seems to put a lot of effort into this part 😅.&lt;/p&gt;

&lt;p&gt;How come? Each API is explained in great detail and provides good and bad ways to use them.&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%2Fhbx0tcwztup1zjxl4se5.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%2Fhbx0tcwztup1zjxl4se5.png" alt="Built-in React hooks" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This section expose APIs from &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;react-dom&lt;/code&gt;. and the &lt;code&gt;Legacy APIs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe8oug8y3t154ucjs614.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%2Ffe8oug8y3t154ucjs614.png" alt="APIs" width="708" height="1230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Community &amp;amp; Blog Section
&lt;/h2&gt;

&lt;p&gt;And the two last sections. People behind this and latest update.&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%2Fays1ubwnqginngcaqtps.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%2Fays1ubwnqginngcaqtps.png" alt="Community" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thousand claps 👏 for you guys that shipping this milestone! Catch them &lt;a href="https://react.dev/community/docs-contributors" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And never miss any news from the React team...&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%2Fsmu6wxa3rp17nnocs8qm.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%2Fsmu6wxa3rp17nnocs8qm.png" alt="Blog" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/dan_abramov"&gt;@dan_abramov&lt;/a&gt; and friends (sorry guys I can't mention you one-by-one :3) have worked hard until this release. I follow Dan on Twitter and he really passionate about the docs.&lt;/p&gt;

&lt;p&gt;The new docs is game changing. Focusing the content for all audience. More illustration, playground, use-cases, and better detailed explanation.&lt;/p&gt;

&lt;p&gt;And the most important. Dark theme! 😅&lt;/p&gt;

&lt;p&gt;I believe they won't stop here. Friendly and clear documentation is one of the most things React community wants.&lt;/p&gt;

&lt;p&gt;See you guys on the next improvement 👋...&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Polymorphic component</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Thu, 09 Mar 2023 11:05:02 +0000</pubDate>
      <link>https://dev.to/thexdev/polymorphic-component-2737</link>
      <guid>https://dev.to/thexdev/polymorphic-component-2737</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Polymorphic component is a React component that has ability to use other HTML element as the returned element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of polymorphic component&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  About
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With this approach, it gives you a control to customize the returned element from a component.&lt;/p&gt;

&lt;p&gt;This is one of UI component that implement polymorphic component.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mantinedev" rel="noopener noreferrer"&gt;
        mantinedev
      &lt;/a&gt; / &lt;a href="https://github.com/mantinedev/mantine" rel="noopener noreferrer"&gt;
        mantine
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A fully featured React components library
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
    &lt;a href="https://go.warp.dev/mantine" rel="nofollow noopener noreferrer"&gt;
        &lt;sup&gt;Special thanks to:&lt;/sup&gt;
        &lt;br&gt;
        &lt;img alt="Warp sponsorship" width="400" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fwarpdotdev%2Fbrand-assets%2Fraw%2Fmain%2FGithub%2FSponsor%2FWarp-Github-LG-02.png"&gt;
        &lt;br&gt;
        Warp, built for coding with multiple AI agents
        &lt;br&gt;
        &lt;sup&gt;Available for macOS, Linux and Windows&lt;/sup&gt;
    &lt;/a&gt;
&lt;/div&gt;



&lt;div&gt;
    &lt;a href="https://formengine.io/?utm_source=github&amp;amp;utm_medium=hero-banner&amp;amp;utm_campaign=mantine-readme" rel="nofollow noopener noreferrer"&gt;
        &lt;sup&gt;Special thanks to:&lt;/sup&gt;
        &lt;br&gt;
        &lt;img alt="Warp sponsorship" width="400" src="https://camo.githubusercontent.com/b95dcc5d1607f5f8193dc5191234ae0c7083ad55ff5f6de4dab05981e31bbf94/68747470733a2f2f666f726d656e67696e652e696f2f6164732d696d616765732f62616e6e6572322e706e673f763d31"&gt;
        &lt;br&gt;
        Drag and Drop React Complex Form Builder Library
        &lt;br&gt;
        &lt;sup&gt;Build and customize complex React forms in minutes. Seamlessly integrate a no-code form designer for your end-users or your internal tools&lt;/sup&gt;
    &lt;/a&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mantine&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/mantinedev/mantine/blob/master/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/07dffc14bccf4367e84bffa3482cd623c83d284d817432e899829c0718e74e63/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f406d616e74696e652f636f7265" alt="NPM"&gt;&lt;/a&gt;
&lt;a href="https://opencollective.com/mantinedev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/67acea83ac926250a484378a096c5ee184f0c21dca70803df7ba1968ff7aac44/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f6d616e74696e656465762f6261636b6572732f62616467652e737667" alt="Backers"&gt;&lt;/a&gt;
&lt;a href="https://github.com/mantinedev/mantine/graphs/contributors" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c6cb6c8754803698c4ca51149c37bf1008e16b79870b209ed38004e8cf3b3969/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732f6d616e74696e656465762f6d616e74696e65" alt="GitHub contributors"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/@mantine/core" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d0e164784fd0a5ec5903e4ff548019e9b20418ceb76355cb5feadef3ad59434d/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f406d616e74696e652f636f7265" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/@mantine/hooks" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e71bc624b1d2e26c871f03fe9d7bdb271e527742d3b7b95d8dadb5187d614bd2/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f406d616e74696e652f686f6f6b73" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/mantinedev/mantine/labels/help%20wanted" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e054be06ef90dfaf300687ec92c55f369ae561c74240aa61ff87c7fc8c8f5c48/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6162656c732f6d616e74696e656465762f6d616e74696e652f68656c7025323077616e7465643f6c6162656c3d436f6e74726962757465" alt="Help wanted"&gt;&lt;/a&gt;
&lt;a href="https://discord.gg/wbH82zuWMN" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4c0ebb3690299f4714995be87a19cb2d9993644542ffff79ce1bbccd94999d87/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436861742532306f6e2d446973636f72642d253233353836356632" alt="Discord"&gt;&lt;/a&gt;
&lt;a href="https://x.com/mantinedev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/010503fe26c124c480bac7420f5ef4284317c12df3625d87a6507ba6e4424874/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6d616e74696e656465763f7374796c653d736f6369616c" alt="X Follow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Links&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mantine.dev/" rel="nofollow noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mantine.dev/contribute" rel="nofollow noopener noreferrer"&gt;Contribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mantinedev/mantine/discussions" rel="noopener noreferrer"&gt;Ask question or give feedback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mantine.dev/changelog/all-releases" rel="nofollow noopener noreferrer"&gt;Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/mantinedev" rel="nofollow noopener noreferrer"&gt;Follow on X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/wbH82zuWMN" rel="nofollow noopener noreferrer"&gt;Join Discord community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Packages&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/hooks/package/" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/hooks&lt;/code&gt;&lt;/a&gt; – collection of 50+ hooks for state and UI management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/core/package/" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/core&lt;/code&gt;&lt;/a&gt; – core components library – 100+ components&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/form/use-form" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/form&lt;/code&gt;&lt;/a&gt; – forms management library&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/charts/getting-started/" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/charts&lt;/code&gt;&lt;/a&gt; – recharts based charts library&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/notifications" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/notifications&lt;/code&gt;&lt;/a&gt; – a fully featured notifications system&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/spotlight" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/spotlight&lt;/code&gt;&lt;/a&gt; – &lt;code&gt;Ctrl + K&lt;/code&gt; command center for your application&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/code-highlight/" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/code-highlight&lt;/code&gt;&lt;/a&gt; – code highlight built with &lt;a href="https://highlightjs.org/" rel="nofollow noopener noreferrer"&gt;highlight.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/tiptap" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/tiptap&lt;/code&gt;&lt;/a&gt; – a Tiptap based rich text editor&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/dropzone" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/dropzone&lt;/code&gt;&lt;/a&gt; – manages files drag 'n' drop to an area or entire screen&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/carousel" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/carousel&lt;/code&gt;&lt;/a&gt; – Carousel component&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/nprogress" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/nprogress&lt;/code&gt;&lt;/a&gt; – navigation progress&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mantine.dev/x/modals" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;@mantine/modals&lt;/code&gt;&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mantinedev/mantine" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When building user interface, we often facing an issue where a component not flexible enough.&lt;/p&gt;

&lt;p&gt;Let's say you have a component like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;You can use component above to create a beautiful button. Nothing wrong with that component. Until someday you want create a link with same style with the &lt;code&gt;&amp;lt;button /&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Maybe you will use this approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;To next page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course it should work, but the code doesn't look so fluent. Meaning to say. If you use HTML, you can write it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We assume &amp;lt;a /&amp;gt; using same styling with &amp;lt;button /&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;To next page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the problem above, polymorphic component offers you a solution like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;To next page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See? You don't need to wrap the &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; component using &lt;code&gt;&amp;lt;a /&amp;gt;&lt;/code&gt; because it's automatically convert the the returned element to &lt;code&gt;&amp;lt;a /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building The Component
&lt;/h2&gt;

&lt;p&gt;Now let's build the component and it's very easy. All you need is only React &lt;code&gt;createElement&lt;/code&gt; API.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;br&gt;
Read the &lt;a href="https://reactjs.org/docs/react-api.html#createelement" rel="noopener noreferrer"&gt;&lt;code&gt;createElement&lt;/code&gt; API documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;We have this component from the previous section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;From this normal component, we will refactor it to polymorphic component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&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="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&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;children&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;Let me explain the code above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- function Button({ children, ...props }) {
&lt;/span&gt;&lt;span class="gi"&gt;+ function Button({ children, as, ...props }) {
&lt;/span&gt;  return React.createElement(as || 'button', props, children);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we added &lt;code&gt;as&lt;/code&gt; props. This props holds a value of what element will returned.&lt;/p&gt;

&lt;p&gt;It's not a must to name it &lt;code&gt;as&lt;/code&gt;. Some UI library name it &lt;code&gt;element&lt;/code&gt;, &lt;code&gt;component&lt;/code&gt;, or whatever you like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;function Button({ children, as, ...props }) {
&lt;/span&gt;&lt;span class="gd"&gt;- return &amp;lt;button {...props}&amp;gt;{children}&amp;lt;/button&amp;gt;;
&lt;/span&gt;&lt;span class="gi"&gt;+ return React.createElement(as || 'button', props, children);
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also changed the JSX to &lt;code&gt;createElement&lt;/code&gt; API to give us more control when creating the component.&lt;/p&gt;

&lt;p&gt;If you not familiar. Actually when you use JSX, under the hood it will transform your code to &lt;code&gt;createElement&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By using the &lt;code&gt;createElement&lt;/code&gt; API, we are able to conditionally create a component. That's why when you are not passing a value into the &lt;code&gt;as&lt;/code&gt; props, the default element of &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; component is &lt;code&gt;&amp;lt;buttton /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that's it... You have created a polymorphic component.&lt;/p&gt;

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

&lt;p&gt;Polymorphic component may sounds very fancy and difficult, but it's not.&lt;/p&gt;

&lt;p&gt;The term of polymorphic is a general term in computer science. You can read about it &lt;a href="https://en.m.wikipedia.org/wiki/Polymorphism_(computer_science)" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of my favorite backend framework, Laravel, is also has a feature called &lt;a href="https://laravel.com/docs/10.x/eloquent-relationships#polymorphic-relationships" rel="noopener noreferrer"&gt;polymorphic relationships&lt;/a&gt; which use this term.&lt;/p&gt;

&lt;p&gt;In React world, polymorphic component refers to an ability of a component that can returns different element with a same style without removing the default functionality.&lt;/p&gt;

&lt;p&gt;It's really help when you facing a problem where you want to use other HTML with a same style.&lt;/p&gt;

&lt;p&gt;I hope it gives you something. Thanks for reading :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/thexdev" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simplify state with reducer</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Wed, 08 Mar 2023 08:48:18 +0000</pubDate>
      <link>https://dev.to/thexdev/simplify-state-with-reducer-28bn</link>
      <guid>https://dev.to/thexdev/simplify-state-with-reducer-28bn</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;React state is good to store a reactive data. When the data changes, the UI will re-render and shwoing the latest update.&lt;/p&gt;

&lt;p&gt;Complex UI also need more than one state. Possibly more than three.&lt;/p&gt;

&lt;p&gt;To simplify manage the state, instead of updating the state one by one using its setter function, it's better to put all states in one place and update it according to event occured using &lt;code&gt;dispatch()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of end result&lt;/span&gt;

&lt;span class="c1"&gt;// From this&lt;/span&gt;
&lt;span class="nf"&gt;setLoading&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="nf"&gt;setVisible&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="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// To this&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading_started&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status_changed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible_toggled&lt;/span&gt;&lt;span class="dl"&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://reactjs.org/docs/hooks-reference.html#usereducer" rel="noopener noreferrer"&gt;React reducer API&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We love state because it makes our apps interactive with less of code, but managing lots of state can be tricky.&lt;/p&gt;

&lt;p&gt;Imagine we have a form component. It's very common case that a form can have mutiple state inside of it. For example, a form may have states for loading, status, form submit, etc.&lt;/p&gt;

&lt;p&gt;The reason why we do this because we want to tell the users what happen to the current process.&lt;/p&gt;

&lt;p&gt;With so many states it is a good advice if you put all states inside one place. A large, maintainable and consistent shape.&lt;/p&gt;

&lt;p&gt;And now, we are going to explore one of built-in React API to create our own shape to simplify managing the states.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Distraction
&lt;/h2&gt;

&lt;p&gt;A form commonly use an alert component to inform the users that their data is successfully processed or not.&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%2Fmf9ztk2tb5q403oqz3ox.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%2Fmf9ztk2tb5q403oqz3ox.png" alt="A form state changed to success" width="800" height="315"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An alert component appears with different style according to the &lt;code&gt;status&lt;/code&gt; state.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;...and your code basically do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Theres nothing wrong with that code above. But, could you imagine managing many states inside a component? BTW, let's add more complexity to the UI.&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%2Fybb6wgv5io4bszkriscm.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%2Fybb6wgv5io4bszkriscm.png" alt="Loading changed to false" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what the changes does. When user clicks the submit button, the button text change to "Loading...". Indicating that the data is being processed. The button is disabled to prevent user clicks multiple times until the process done.&lt;/p&gt;




&lt;p&gt;So far we have two states. The &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;loading&lt;/code&gt;. Can you spot the "distraction"? I think not yet.&lt;/p&gt;

&lt;p&gt;Some particular apps using an overlay to display the form to minimize the page transition which will improve UX. The form should appear when user click a "trigger" and can be closed.&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%2Frv53ksxjtkejdaskpwc8.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%2Frv53ksxjtkejdaskpwc8.png" alt="User clicks Add Product button" width="800" height="912"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if we combining all states we should have &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt; and &lt;code&gt;visible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's assume we have declared those states inside our component and to change the value for each state, you use the setter function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;setVisible&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="nf"&gt;setLoading&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="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As your UI getting more complex, you will have more states. More states meaning more setter functions and that's the first distraction.&lt;/p&gt;

&lt;p&gt;With so many setter functions, the behaviour of consistency to update the state a little bit lost because to update a state you need a specific setter function.&lt;/p&gt;




&lt;p&gt;If using multiple setter function in a single component isn't make you distracted, let's take a look to &lt;a href="https://en.wikipedia.org/wiki/Maintainability" rel="noopener noreferrer"&gt;maintainability&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you develop a text editor for eCommerce website. So the seller can format the description part of a product to provide better information.&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%2Fjjhlwtudz2vpfxouxyu2.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%2Fjjhlwtudz2vpfxouxyu2.png" alt="Text editor" width="800" height="463"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example of simple text editor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;From image above we possibly have four states inside the text editor. Which is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;formatter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;showOptions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;letterCount&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although this is very simple text editor, you need to extract the UI into components based on its functionality and this is the problem come from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Just example :)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TextEditor&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ModeSwitch&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContentBody&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LetterCount&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of components need sharing states to act normally. For example the &lt;code&gt;&amp;lt;Formatter /&amp;gt;&lt;/code&gt; may use the &lt;code&gt;mode&lt;/code&gt; state because the formatter appear based on what current mode is being used. If user switch to Markdown, the formatter should disappear and vice versa.&lt;/p&gt;

&lt;p&gt;The question is how do we share the states through all components?&lt;/p&gt;

&lt;p&gt;The answer is very simple. Yes, using the Context. But, how? Like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// state declarations here&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextEditorProvider&lt;/span&gt;
        &lt;span class="na"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formatter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;showOptions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showOptions&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;letterCount&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;letterCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ModeSwitch&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContentBody&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LetterCount&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TextEditorProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And inside the &lt;code&gt;&amp;lt;Formatter /&amp;gt;&lt;/code&gt; component, use the &lt;code&gt;mode&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TextEditorContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;Another problem is the props of &lt;code&gt;&amp;lt;TextEditorProvider /&amp;gt;&lt;/code&gt; grow exponentially as you add more state to the &lt;code&gt;&amp;lt;TextEditor /&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;So, do we have better solution? Well, of course, yes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flux Architecture
&lt;/h2&gt;

&lt;p&gt;We are not going to discuss Flux as a whole because it's a huge topic. What we're gonna do is to getting know about the main idea of Flux Architecture.&lt;/p&gt;

&lt;p&gt;Flux Architecture or Flux is a pattern to manage states that live inside your component.&lt;/p&gt;

&lt;p&gt;It's not a framework, but something like idealogy similar to &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" rel="noopener noreferrer"&gt;MVC&lt;/a&gt; pattern. Even though it has minimal library to simplify our work.&lt;/p&gt;

&lt;p&gt;Flux has four main parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dispatcher&lt;/li&gt;
&lt;li&gt;Stores&lt;/li&gt;
&lt;li&gt;Actions&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;/ul&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%2Ffacebook.github.io%2Fflux%2Fimg%2Foverview%2Fflux-simple-f8-diagram-with-client-action-1300w.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%2Ffacebook.github.io%2Fflux%2Fimg%2Foverview%2Fflux-simple-f8-diagram-with-client-action-1300w.png" alt="Data in a Flux application flows in a single direction" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://facebook.github.io/flux/docs/in-depth-overview" rel="noopener noreferrer"&gt;https://facebook.github.io/flux/docs/in-depth-overview&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Dispatcher
&lt;/h3&gt;

&lt;p&gt;A dispatcher is a central place to updating the state. It is similar with setter function of React state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&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="c1"&gt;// This is the dispatcher.&lt;/span&gt;
&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That code above is not the actual flux dispatcher.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Stores
&lt;/h3&gt;

&lt;p&gt;A store is what holds the data of an application. So, instead of expose the data publicly, it's wrap the data in the store and perform operation inside it (via dispatcher).&lt;/p&gt;

&lt;p&gt;You can see &lt;a href="https://github.com/facebook/flux/blob/main/examples/flux-flow/src/AppStore.js" rel="noopener noreferrer"&gt;here&lt;/a&gt; for an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;An action is a simple object that describe of what condition or event that being occurred. Action is used by dispatcher to determine what operation needs to be performed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MODE_SWITCHED_TO_MARKDOWN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mode-switched&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;markdown&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;MODE_SWITCHED_TO_EDITOR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mode-switched&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Dispatch an action&lt;/span&gt;
&lt;span class="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MODE_SWITCHED_TO_MARKDOWN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an action need to pass a data or you want the action dynamic, you can use &lt;strong&gt;Action Creator&lt;/strong&gt;. Action Creator is a simple function that produce an action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;switchMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mode_switched&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;switchMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&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 to remember that the most important part is &lt;code&gt;type&lt;/code&gt; because we need this information to identify what operation should be performed.&lt;/p&gt;




&lt;p&gt;The why Flux pattern can provide a better solution rather than raw React state because with Flux we can do many things. Not only holds a data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separation of concerns&lt;/li&gt;
&lt;li&gt;Easier Debugging&lt;/li&gt;
&lt;li&gt;Code predictability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list above is some of Flux benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Views
&lt;/h3&gt;

&lt;p&gt;Nothing special with views. Views is component you made that may use the store or dispatch an action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of component that dispatch an action&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ModeSwitch&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switcher&lt;/span&gt;
    &lt;span class="na"&gt;onSwitch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MODE_SWITCHED_TO_EDITOR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&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;See?  Now it looks maintainable and consistent because we don't need to use specific setter function for each state.&lt;/p&gt;

&lt;p&gt;You might be feel this approach little bit confused because I only show the main idea and use part of the code. But, once you got the main idea I ensure you will love this approach.&lt;/p&gt;

&lt;p&gt;And the reason why I only show the main idea because Flux is currently in maintenance mode, but the idea still live and adopted by &lt;code&gt;React.useReducer&lt;/code&gt; and &lt;code&gt;Redux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get more information about Flux, go to their official website &lt;a href="https://facebook.github.io/flux/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining Context And Flux
&lt;/h2&gt;

&lt;p&gt;Flux by defult is shareable between all views. That means we don't need to pass the Flux data into the Context.&lt;/p&gt;

&lt;p&gt;Since Flux is in maintenance mode, it's not good practice to use Flux anymore. But, follow the main idea is a good deal, tho.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note:&lt;br&gt;
The maintenance mode is refers to &lt;a href="https://www.npmjs.com/package/flux" rel="noopener noreferrer"&gt;Flux library&lt;/a&gt; not the main idea.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Is it possible to implement the Flux idea and share it between components through Context? The answer is yes.&lt;/p&gt;

&lt;p&gt;Let's implement the Context first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// text-editor-context.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TextEditorContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TextEditorProvider&lt;/span&gt; &lt;span class="o"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextEditorContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;store&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;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dispatch&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;dispatch&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;props&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;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;TextEditorContext&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
};

export default TextEditorContext;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Context role is act like a bridge that connects all components to consume shareable state. Just it.&lt;/p&gt;

&lt;p&gt;So, how implement the Flux? since the library itself is not continued by the maintainer.&lt;/p&gt;

&lt;p&gt;Therefore, please welcome...&lt;/p&gt;

&lt;h3&gt;
  
  
  React.useReducer
&lt;/h3&gt;

&lt;p&gt;What is &lt;code&gt;React.useReducer&lt;/code&gt;? Well, because you already know about Flux. It is simplified Flux without shareable ability. Therefore, we use Context to make it shareable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.useReducer&lt;/code&gt; or simplified called reducer is slightly different compared to Flux.&lt;/p&gt;

&lt;p&gt;Flux is require you to create a class that extends &lt;code&gt;ReduceStore&lt;/code&gt; from the Flux library. While &lt;code&gt;React.useReducer&lt;/code&gt; is a hook and takes two arguments to operates. The &lt;code&gt;reducer&lt;/code&gt; and &lt;code&gt;inititalState&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Read more about React.useState &lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With &lt;code&gt;React.useState&lt;/code&gt; we can create a Flux-like state and should answer the question from the previous section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of reducer.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;showOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;letterCount&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="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Actions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;switchMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mode-switched&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Rest of actions...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mode-switched&lt;/span&gt;&lt;span class="dl"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formatter-changed&lt;/span&gt;&lt;span class="dl"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;options-toggled&lt;/span&gt;&lt;span class="dl"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;showOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showOptions&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;letter-count-increased&lt;/span&gt;&lt;span class="dl"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;letterCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;letterCount&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;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;letter-count-decreased&lt;/span&gt;&lt;span class="dl"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;letterCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;letterCount&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unidentified Type Given.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextEditorProvider&lt;/span&gt; &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ModeSwitch&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ContentBody&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LetterCount&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TextEditorProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now all components wrapped inside &lt;code&gt;&amp;lt;TextEditorProvider /&amp;gt;&lt;/code&gt; should be able to access the &lt;code&gt;state&lt;/code&gt; object and &lt;code&gt;dispatch&lt;/code&gt; API.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Final Result
&lt;/h2&gt;

&lt;p&gt;After all, we are going to combine all solutions.&lt;/p&gt;

&lt;p&gt;The inconsistency problem has been solved from code above. Theres no specific setter function. Theres only &lt;code&gt;dispatch()&lt;/code&gt; function to update specified state.&lt;/p&gt;

&lt;p&gt;The maintainability problem is also solved because if you want add new feature or states, you are not polluting the &lt;code&gt;&amp;lt;TextEditorProvider /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of adding props, you just need to update the &lt;code&gt;initialState&lt;/code&gt; and adding some actions or action creators.&lt;/p&gt;

&lt;p&gt;And now you can use the states across all components...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ModeSwitch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TextEditorContext&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switcher&lt;/span&gt;
    &lt;span class="na"&gt;onSwitch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;switchMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;markdown&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="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;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 jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Theres no need to destruct the array :)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TextEditorContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;You can even make the context simpler using a custom hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useStore&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TextEditorContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Use it like this&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Managing state can be tricky for complex application. Using combination of state and context is good, but we have better solution by using reducer.&lt;/p&gt;

&lt;p&gt;Reducer is ensure us to update the state only using the &lt;code&gt;dispatch()&lt;/code&gt; API. Minimizing distraction when using setter function, improve maintainability and consistency.&lt;/p&gt;

&lt;p&gt;The Flux pattern is every useful for large application. Separation of concern, easy to debug and predictability. All of those features are needed by long-runnung application.&lt;/p&gt;

&lt;p&gt;Luckly, reducer is already implement this pattern. Even though with simplification, but it still worth.&lt;/p&gt;

&lt;p&gt;By combining context and reducer, you got Flux with simpler approach. Awesome!&lt;/p&gt;

&lt;p&gt;FIY, one of top library that use Flux idea is &lt;a href="https://redux.js.org" rel="noopener noreferrer"&gt;Redux&lt;/a&gt;. And this is my favorite React state management.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/thexdev" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520macbook%26emoji%3D%25F0%259F%2592%25BB%26slug%3Dthexdev%26button_colour%3DFFDD00%26font_colour%3D000000%26font_family%3DPoppins%26outline_colour%3D000000%26coffee_colour%3Dffffff" width="244.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Test React component that fetching data</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Sat, 04 Mar 2023 14:18:59 +0000</pubDate>
      <link>https://dev.to/thexdev/test-react-component-that-fetching-data-390p</link>
      <guid>https://dev.to/thexdev/test-react-component-that-fetching-data-390p</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We are going to use &lt;a href="https://mswjs.io" rel="noopener noreferrer"&gt;Mock Service Worker&lt;/a&gt; to fake the API. So, instead directly calling the API or mock the &lt;code&gt;window.fetch&lt;/code&gt; it's better to mock the server behaviour.&lt;/p&gt;

&lt;p&gt;It gives us a sandbox to play with the API server without polluting the &lt;code&gt;window.fetch&lt;/code&gt; and no need to setup test API server for testing purpose.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://github.com/kettanaito" rel="noopener noreferrer"&gt;Artem Zakharchenko&lt;/a&gt; that has made a useful tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You have created a beautiful &lt;code&gt;Feed&lt;/code&gt; feature on your site and now you want to test that feature.&lt;/p&gt;

&lt;p&gt;Your code is look like this&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Feed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;feeds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFeeds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctl&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;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.domain.com/feeds&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setFeeds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Log the error&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ctl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;feeds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&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;Though, it's really simple frature where you want to show users feed to the UI.&lt;/p&gt;

&lt;p&gt;Somehow you confused about how to test the feature because you "must" fetch the feeds data from the API, but since this is a test you won't it calls directly to the API.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Journey
&lt;/h2&gt;

&lt;p&gt;Now you are searching possible solutions on the Internet. Because you use React and of course use Jest and testing-library (it is default setup from CRA), someone suggest you to mock the &lt;code&gt;window.fetch&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;You intersted and put the solution in your test like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import all dependencies... &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/** Feed objects here */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nf"&gt;beforeAll&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Feed Feature Test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows users feed&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValueOnce&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;// Your testing goes here... &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;You test the code and it looks green (meaning your test is pass) and you happy with that.&lt;/p&gt;



&lt;p&gt;Tomorrow has come. You forgot about the "empty state" UI for Feed feature and today you made it.&lt;/p&gt;

&lt;p&gt;Because the empty state UI need en error &lt;a href="https://id.wikipedia.org/wiki/HTTP_404" rel="noopener noreferrer"&gt;HTTP NOT FOUND&lt;/a&gt;, you need to refactor the test.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import all dependencies... &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/** Feed objects here */&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;MOCK_FEEDS_NOT_FOUND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nf"&gt;beforeAll&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&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="nf"&gt;beforeEach&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;restoreAllMocks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Feed Feature Test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows empty state UI when feeds not found&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValueOnce&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS_NOT_FOUND&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;// Your testing goes here... &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows users feed&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValueOnce&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;// Your testing goes here... &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;Your test is passes, and you happy again.&lt;/p&gt;



&lt;p&gt;The next morning, you received calls from project manager. He want you to add a "like (❤️)" button and you do it.&lt;/p&gt;

&lt;p&gt;From this task, you have to update the feature to fetch two API endpoints. First you must use the &lt;code&gt;GET /feeds&lt;/code&gt; and then &lt;code&gt;POST /feeds/{id}/like&lt;/code&gt; to perform "like this feed".&lt;/p&gt;

&lt;p&gt;After adding some codes, you refactor the test again, but realise that the mocked fetch doesn't care of the URL. What ever API endpoint you hit, it always returns the same response and potential a bugs on the future.&lt;/p&gt;

&lt;p&gt;The test now is look like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import all dependencies... &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/** Feed objects here */&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;MOCK_FEEDS_NOT_FOUND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nf"&gt;beforeAll&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&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="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/feeds&lt;/span&gt;&lt;span class="dl"&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="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/feeds/1/like&lt;/span&gt;&lt;span class="dl"&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="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;liked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unhandled request: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Feed Feature Test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows empty state UI when feeds not found&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="c1"&gt;// Your testing goes here... &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows users feed&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="c1"&gt;// Your testing goes here... &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should able to like the feed&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="c1"&gt;// Your testing goes here...&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 tests are passes except the first one. You asking "why?" then realise there is no request handler for &lt;code&gt;GET /feeds&lt;/code&gt; with &lt;code&gt;404&lt;/code&gt; http status.&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%2Fwdpxevkdpzpaecnt1etr.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%2Fwdpxevkdpzpaecnt1etr.png" alt="Debugging be like" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://id.pinterest.com/pin/784259722590566564/" rel="noopener noreferrer"&gt;https://id.pinterest.com/pin/784259722590566564/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Luckly, there is a tool called &lt;a href="https://mswjs.io" rel="noopener noreferrer"&gt;Mock Service Worker&lt;/a&gt;. It is a mocking tool for API and live in the network level.&lt;/p&gt;

&lt;p&gt;Simply imagine that you can mock your API server and use it inside your test without makes you headache.&lt;/p&gt;

&lt;p&gt;And the interesting part of this are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support Rest API and GraphQL&lt;/li&gt;
&lt;li&gt;Support Node and Browser (meaning you can use it with Express, etc)&lt;/li&gt;
&lt;li&gt;And many more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enough for explaining, let's install the requirement and refactor the tests.&lt;/p&gt;



&lt;p&gt;First, install the &lt;code&gt;msw&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; msw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To use the MSW, you need to make request handlers with specific HTTP method and URL. So, it gives you an ability to make &lt;code&gt;GET 200 /feeds&lt;/code&gt; and &lt;code&gt;GET 404 /feeds&lt;/code&gt;. It also support URL parameter like this &lt;code&gt;/feeds/:feedId/like&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now update the test like this...&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import all dependencies... &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;msw/node&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;MOCK_FEEDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/** Feed objects here */&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;MOCK_FEEDS_NOT_FOUND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`https://api.domain.com/feeds/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultHandlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MOCK_FEEDS&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MOCK_FEEDS_NOT_FOUND&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setupServer&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;defaultHandlers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Feed Feature Test&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;beforeAll&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;afterEach&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetHandlers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;afterAll&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows empty state UI when feeds not found&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="c1"&gt;// Your testing goes here... &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should shows users feed&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="c1"&gt;// Your testing goes here... &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should able to like the feed&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="c1"&gt;// Adds the "POST /feeds/:feedId/like" request handler as a part of this test.&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;rest&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="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feeds/:feedId/like&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;liked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Your testing goes here...&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;Boom! your tests are passes. Not only the tests are passes it also provide better DX because you can easily create powerful URL routing.&lt;/p&gt;

&lt;p&gt;You can also split the handlers into another file to prevent writing the handlers repeatedly. Making it reusable across all tests.&lt;/p&gt;

&lt;p&gt;Not only provide better DX, MSW also offers you HTTP Cookie and other HTTP features. Awesome!&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mocking (and testing) HTTP request is one of challenging part, but MSW comes with powerful feature, cross-platform and use simple approach to tackle this problem.&lt;/p&gt;

&lt;p&gt;MSW provide native-like approach by intercepting the network and returns the handlers we made instead of the real one. Prevent you to pollute the &lt;code&gt;window.fetch&lt;/code&gt; by mocking it and potentially caused bugs.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mswjs" rel="noopener noreferrer"&gt;
        mswjs
      &lt;/a&gt; / &lt;a href="https://github.com/mswjs/msw" rel="noopener noreferrer"&gt;
        msw
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Industry standard API mocking for JavaScript.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;br&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/mswjs/msw/media/msw-logo.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmswjs%2Fmsw%2Fmedia%2Fmsw-logo.svg" width="100" alt="The Mock Service Worker logo"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mock Service Worker&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Industry standard API mocking for JavaScript.&lt;/p&gt;

&lt;p&gt;
   &lt;a href="https://kettanaito.com/discord" rel="nofollow noopener noreferrer"&gt;Join our Discord server&lt;/a&gt;
&lt;/p&gt;



&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seamless&lt;/strong&gt;. A dedicated layer of requests interception at your disposal. Keep your application's code and tests unaware of whether something is mocked or not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deviation-free&lt;/strong&gt;. Request the same production resources and test the actual behavior of your app. Augment an existing API, or design it as you go when there is none.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Familiar &amp;amp; Powerful&lt;/strong&gt;. Use &lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt;-like routing syntax to intercept requests. Use parameters, wildcards, and regular expressions to match requests, and respond with necessary status codes, headers, cookies, delays, or completely custom resolvers.&lt;/li&gt;
&lt;/ul&gt;



&lt;br&gt;
&lt;blockquote&gt;

&lt;p&gt;"&lt;em&gt;I found MSW and was thrilled that not only could I still see the mocked responses in my DevTools, but that the mocks didn't have to be written in a Service Worker and could instead live alongside the rest of my app. This made it silly easy&lt;/em&gt;…&lt;/p&gt;


&lt;/blockquote&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mswjs/msw" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/thexdev" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520macbook%26emoji%3D%25F0%259F%2592%25BB%26slug%3Dthexdev%26button_colour%3DFFDD00%26font_colour%3D000000%26font_family%3DPoppins%26outline_colour%3D000000%26coffee_colour%3Dffffff" width="244.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Refs is more than enough</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Mon, 20 Feb 2023 20:13:14 +0000</pubDate>
      <link>https://dev.to/thexdev/refs-is-more-than-enough-4a2a</link>
      <guid>https://dev.to/thexdev/refs-is-more-than-enough-4a2a</guid>
      <description>&lt;p&gt;This story started when I learning React.js for the first time. Where I see a lot of influencers overused the &lt;code&gt;React.useState&lt;/code&gt; or generally speaking, a React.js state.&lt;/p&gt;

&lt;p&gt;Let's be honest, we ever put a React state on every HTML input we have. When it has two inputs, no problem occur.&lt;/p&gt;

&lt;p&gt;Sometime, your PM tells you to add a new feature and guest what? You add more and more state. Leading your application slow because of unnecessary re-render.&lt;/p&gt;

&lt;p&gt;And now, you confuse why the application so slow even crashed on older browser.&lt;/p&gt;

&lt;p&gt;...or maybe, Refs is the answer you looking for?&lt;/p&gt;

&lt;h2&gt;
  
  
  State: The Sweat Part
&lt;/h2&gt;

&lt;p&gt;No doubt. React state helps us when dealing with interactive UI. For example you have a filter feature. You can filter your data by date, category, etc and display the filtered data.&lt;/p&gt;

&lt;p&gt;Normally, your code looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFilter&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="kc"&gt;null&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;fetchDataWithFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="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;setFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/** Fetching data... */&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Filter by: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fetchDataWithFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"monthly"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Monthly&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"cluster"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cluster&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** data display goes here... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As the result, you have beautiful and interactive filter feature.&lt;/p&gt;

&lt;p&gt;At this point, theres no thing wrong with this approach. But, what happens when you have a case like managing values inside a form?.&lt;/p&gt;
&lt;h2&gt;
  
  
  State: The Sour Part
&lt;/h2&gt;

&lt;p&gt;When you have a case like product entry form, normally you have &amp;gt;= 5 input fields. If you use React state for each input field to listen for value changes it's not good because your form will re-renders many times.&lt;/p&gt;

&lt;p&gt;Let's imagine your client types 5 (average) letters for each input field and the form should have 5 (key hits) * 5 (input fields) = 25 (re-renders).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductEntry&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="cm"&gt;/** States declarations... */&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;onKeyUp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt; &lt;span class="na"&gt;onKeyUp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"stocks"&lt;/span&gt; &lt;span class="na"&gt;onKeyUp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setStocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Rest of input fields... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&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 benefit is you always got uptodate values where you can validate the values on the fly. But, you will have performance worst.&lt;/p&gt;
&lt;h2&gt;
  
  
  Refs: The Healthy Sweat
&lt;/h2&gt;

&lt;p&gt;Instead of putting states for each input fields, you can use ref for getting the values without causing re-renders.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductEntry&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="cm"&gt;/** Refs declarations... */&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputNameRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputPriceRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"stocks"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputStocksRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Rest of input fields... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&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;With this approach, no matter how much your client types in the input fields, React shouldn't re-renders the form.&lt;/p&gt;

&lt;p&gt;The downside is you need to add extra step for process the values (validate, sanitize, etc).&lt;/p&gt;

&lt;p&gt;We can use a pattern called observer to handle the downside. Instead of process the values on the fly, we process it when some event fired. Normally when the form is being submitted.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductEntry&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="cm"&gt;/** Refs declarations... */&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submit&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="c1"&gt;// 1. Collect all values&lt;/span&gt;
      &lt;span class="c1"&gt;// 2. Validate&lt;/span&gt;
      &lt;span class="c1"&gt;// 3. Sanitize&lt;/span&gt;
      &lt;span class="c1"&gt;// 4. Perform HTTP request&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputNameRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputPriceRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"stocks"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputStocksRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Rest of input fields... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save Product&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&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;So, before the button is clicked, no actions is running and less of re-renders.&lt;/p&gt;
&lt;h2&gt;
  
  
  Objectives
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Use state wisely
&lt;/h3&gt;

&lt;p&gt;State makes our app interactive and it's awesome. When dealing with large app, you should pay attention of every state change.&lt;/p&gt;

&lt;p&gt;Too many re-renders is not good for you app. Except you isolate it, so others parts not affected.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use refs with observer pattern
&lt;/h3&gt;

&lt;p&gt;It sounds every technical, but actually it's very simple concept. Just run your functions when an event fired.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Button clicked -&amp;gt; run submit() function&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Dropdown changed -&amp;gt; run fetchDataWithFilter() function&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside those functions, you can access your refs and process it as usual.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use form validation library
&lt;/h3&gt;

&lt;p&gt;Don't so diligent. You shouldn't to manually validate your form. Use a correct library instead. One of my recommendation is &lt;a href="https://react-hook-form.com/" rel="noopener noreferrer"&gt;react-hook-form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It implement refs and observer pattern. So don't be worry of unnecessary re-renders. And also I have wrote a guide how to use it :).&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/thexdev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F308956%2F368d59b9-afc5-4074-909f-0c4cf76e0683.png" alt="thexdev"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/thexdev/form-validation-with-react-hook-form-94e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Form validation with react-hook-form&lt;/h2&gt;
      &lt;h3&gt;M. Akbar Nugroho ・ Aug 14 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;👋 Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Dockerize Production React.js</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Fri, 07 Oct 2022 19:15:49 +0000</pubDate>
      <link>https://dev.to/thexdev/dockerize-production-reactjs-3ai9</link>
      <guid>https://dev.to/thexdev/dockerize-production-reactjs-3ai9</guid>
      <description>&lt;p&gt;With the popularity of cloud computing, containerization is a common technique used for mid to large scale project because it gives us isolated, scalable and easy way to deploy our application.&lt;/p&gt;

&lt;p&gt;Today we are going to learn and create a production-ready docker image for React.js application. I really exited with this one so, let's start it out 😼.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirement
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, ensure Docker is installed on your machine. If you haven't please install it and come here again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, ensure Node.js is also installed on your machine. We need this to bootstrap our React.js application.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Initialize a Project
&lt;/h2&gt;

&lt;p&gt;Theres so many ways to intializing React.js application. Either manually, pre-built template or front-end tools.&lt;/p&gt;

&lt;p&gt;In this article we are going to use front-end tool called &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; because it's fast and configurable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HINT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may use &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create React App (CRA)&lt;/a&gt; to intialize your application. It's also good and developed by Facebook Open Source too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open your terminal and type the following command.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest docker-production-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A prompt will appear. Just select React and JavaScript.&lt;/p&gt;

&lt;p&gt;Now move to folder &lt;code&gt;docker-production-react&lt;/code&gt; and run the following command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
npm i&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HINT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i&lt;/code&gt; is just aliased command for &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To ensure the initialize process works fine, let's start the local server.&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 dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Open with your browser &lt;code&gt;http://localhost:5173&lt;/code&gt; and you should see something like this.&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%2Fpa28cp8afmlpsd1nbm2c.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%2Fpa28cp8afmlpsd1nbm2c.png" alt="Vite + React" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create Custom Docker Image
&lt;/h2&gt;

&lt;p&gt;In this article, we'll using a technique called multi-stage build. Our goals is to separate the build process of React.js application itself and the web server (to serve the website).&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup For Build Process
&lt;/h3&gt;

&lt;p&gt;First, inside &lt;code&gt;docker-production-react&lt;/code&gt; create a &lt;code&gt;Dockerfile&lt;/code&gt; file and follow snippet below.&lt;/p&gt;

&lt;p&gt;Here, we are using &lt;code&gt;16.17.1-alpine3.16&lt;/code&gt;. I choose alpine linux because it's tiny so, it make build process faster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16.17.1-alpine3.16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The snippet above tells Docker to pull (when hasn't pulled) or use pulled image from Docker Hub to use &lt;code&gt;node:16.17.1-alpine3.16&lt;/code&gt; as the base image for build stage, set the current directory to &lt;code&gt;/usr/app&lt;/code&gt;, running &lt;code&gt;npm ci&lt;/code&gt; and finally build the application using &lt;code&gt;npm run build&lt;/code&gt; command.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup For Web Server
&lt;/h3&gt;

&lt;p&gt;Because React.js application is a static files, we need a simple, yet performant we web server in order the user able to access the application. Therefor I choose Nginx to handle this job.&lt;/p&gt;

&lt;p&gt;From the previous &lt;code&gt;Dockerfile&lt;/code&gt;, follow this snippet.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.23.1-alpine&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /usr/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we tell Docker to use &lt;code&gt;nginx:1.23.1-alpine&lt;/code&gt; as the base image and exposing port 80 (default port Nginx), copy the configuration file and copy our bundled application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HINT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because Nginx act as a common web server and only serve our application, it's OK to not bind the configuration file at runtime.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the Nginx configuration file, create &lt;code&gt;default.conf&lt;/code&gt; file inside &lt;code&gt;docker/nginx/conf.d&lt;/code&gt;.&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="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; docker/nginx/conf.d&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;docker/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;...and follow below snippet.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;server&lt;/span&gt; {
    &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;;
    &lt;span class="n"&gt;root&lt;/span&gt; /&lt;span class="n"&gt;usr&lt;/span&gt;/&lt;span class="n"&gt;share&lt;/span&gt;/&lt;span class="n"&gt;nginx&lt;/span&gt;/&lt;span class="n"&gt;html&lt;/span&gt;;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;.&lt;span class="n"&gt;html&lt;/span&gt;;

    &lt;span class="n"&gt;location&lt;/span&gt; / {
        &lt;span class="n"&gt;try_files&lt;/span&gt; $&lt;span class="n"&gt;uri&lt;/span&gt; $&lt;span class="n"&gt;uri&lt;/span&gt;/ /&lt;span class="n"&gt;index&lt;/span&gt;.&lt;span class="n"&gt;html&lt;/span&gt;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The configuration just serve our application, but you can customize it as your needs.&lt;/p&gt;

&lt;p&gt;Here our final &lt;code&gt;Dockerfile&lt;/code&gt;...&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16.17.1-alpine3.16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.23.1-alpine&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /usr/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  .dockerignore
&lt;/h3&gt;

&lt;p&gt;It's similar with &lt;code&gt;.gitignore&lt;/code&gt;, but it's used when you build your Docker image.&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="nb"&gt;touch&lt;/span&gt; .dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Put it inside &lt;code&gt;.dockerignore&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git
.DS_Store
.env
node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never put sensitive information inside your Docker image. Exclude it using &lt;code&gt;.dockerignore&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Build Phase
&lt;/h2&gt;

&lt;p&gt;Execute this command to build our image.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; web:0.1.0 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ensure the image is available.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Let's verify our works.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; web-1 &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 &lt;span class="nt"&gt;-d&lt;/span&gt; web:0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now open &lt;code&gt;http://localhost&lt;/code&gt; with your browser and you should see something like this.&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%2Fgxkusffawcy085364lfs.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%2Fgxkusffawcy085364lfs.png" alt="Vite + React" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yeay! It's working...&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus: The Source Code
&lt;/h2&gt;

&lt;p&gt;Find it &lt;a href="https://github.com/thexdev/devlabs/tree/main/docker-production-react" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also follow my latest experiment.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/thexdev" rel="noopener noreferrer"&gt;
        thexdev
      &lt;/a&gt; / &lt;a href="https://github.com/thexdev/devlabs" rel="noopener noreferrer"&gt;
        devlabs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🧙‍♂️  Find my latest experiment here! 🪄
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Welcome, the Alchemist! 🧙‍♂️&lt;/h1&gt;

&lt;/div&gt;

&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🧙‍♂️ The Elder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hohoho, are you lost son? This place is full of curiosity that never end. Don't go away too quick son! Take a look and pick freely as you want, hohoho~&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thexdev/devlabs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>docker</category>
      <category>react</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Basic Load Balancing With Docker, NGINX &amp; PHP</title>
      <dc:creator>M. Akbar Nugroho</dc:creator>
      <pubDate>Wed, 05 Oct 2022 11:21:42 +0000</pubDate>
      <link>https://dev.to/thexdev/basic-load-balancing-with-docker-nginx-php-2p08</link>
      <guid>https://dev.to/thexdev/basic-load-balancing-with-docker-nginx-php-2p08</guid>
      <description>&lt;p&gt;This article is a basic knowledge of how to create a load balancer using docker and PHP as its services.&lt;/p&gt;

&lt;p&gt;In real-world use cases, it is more complex than we think and I prefer you to choose a cloud provider then setup your load balancer over there.&lt;/p&gt;

&lt;p&gt;But before you go, reading this article will help you to understand the mental model of load balancing and the purpose of that thing.&lt;/p&gt;

&lt;p&gt;Let's start it out 😼&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Load Balancer
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;In computing, load balancing is the process of distributing a set of tasks over a set of resources (computing units), with the aim of making their overall processing more efficient. Load balancing can optimize the response time and avoid unevenly overloading some compute nodes while other compute nodes are left idle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.m.wikipedia.org/wiki/Load_balancing_(computing)" rel="noopener noreferrer"&gt;Wikipedia - Load Balancing (computing)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I know that fancy words are confusing, so let's simplify that definition.&lt;/p&gt;

&lt;p&gt;A load balancing is a technique in computer field where you have two or more servers to handle the user requests.&lt;/p&gt;

&lt;p&gt;To make this thing more concrete, let's imagine you have a delivery service. Your business can receives 100 packages to deliver in a day, but you only have one currier where its max capacity is handling 10 delivery in a day.&lt;/p&gt;

&lt;p&gt;You realize that you need 10 days to deliver those packages. If one currier can handles 10 delivery in a day, by add 9 more curriers, your business can handles 100 delivery in a day.&lt;/p&gt;

&lt;p&gt;In real-world case, the curriers are act as a server to handle high traffic website like marketplace, movie streaming, etc nearest at a same time.&lt;/p&gt;

&lt;p&gt;This technique is aimed to distribute high traffic workload to two or more servers. So, everyone can be handled by the servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big Picture of Our Goals
&lt;/h2&gt;

&lt;p&gt;At the end of this article, we should be able to create and running one nginx service and two php services.&lt;/p&gt;

&lt;p&gt;We will create and configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom nginx docker image&lt;/li&gt;
&lt;li&gt;Custom php docker image&lt;/li&gt;
&lt;li&gt;Custom docker network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take a look at the following image for better understanding.&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%2Fgr5kqkjuwjt79q2w0pco.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%2Fgr5kqkjuwjt79q2w0pco.png" alt="Docker Load Balancer" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Creating custom NGINX image
&lt;/h2&gt;

&lt;p&gt;Let's start creating a custom nginx image using &lt;code&gt;nginx:1.23.1-alpine&lt;/code&gt; as the base image.&lt;/p&gt;

&lt;p&gt;First, create a directory called &lt;code&gt;docker-basic-lb&lt;/code&gt; with a child &lt;code&gt;proxy&lt;/code&gt;.&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="nb"&gt;mkdir &lt;/span&gt;docker-basic-lb&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;mkdir &lt;/span&gt;docker-basic-lb/proxy&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a &lt;code&gt;Dockerfile&lt;/code&gt;.&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="nb"&gt;cd &lt;/span&gt;docker-basic-lb/proxy&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;Dockerfile&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Open the &lt;code&gt;Dockerfile&lt;/code&gt; and put the codes below...&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.23.1-alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; /etc/nginx/conf.d/default.conf

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create nginx configuration file.&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="nb"&gt;touch &lt;/span&gt;default.conf&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 conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker-basic-lb/proxy/default.conf
&lt;/span&gt;
&lt;span class="n"&gt;upstream&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt; {
  &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;-&lt;span class="m"&gt;1&lt;/span&gt;:&lt;span class="m"&gt;8000&lt;/span&gt;;
  &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;-&lt;span class="m"&gt;2&lt;/span&gt;:&lt;span class="m"&gt;8001&lt;/span&gt;;
}

&lt;span class="n"&gt;server&lt;/span&gt; {
  &lt;span class="n"&gt;location&lt;/span&gt; / {
    &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;://&lt;span class="n"&gt;gateway&lt;/span&gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we create a custom nginx image and its configuration file. Inside the configuration file, we have two servers: &lt;code&gt;service-1&lt;/code&gt; and &lt;code&gt;service-2&lt;/code&gt; with their own port. Don't worry, we will create those services later...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;&lt;br&gt;
In production, we should bind a directory to our custom nginx image for storing the configuration file.&lt;/p&gt;

&lt;p&gt;It's important because when the configuration file changes we don't need to build the image over and over again.&lt;/p&gt;

&lt;p&gt;But, to simplify this article let's put it on inside the image.&lt;/p&gt;
&lt;h2&gt;
  
  
  Task 2: Creating custom PHP docker image
&lt;/h2&gt;

&lt;p&gt;Let's move to &lt;code&gt;docker-basic-lb&lt;/code&gt;.&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="nb"&gt;cd&lt;/span&gt; ../&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a directory inside &lt;code&gt;docker-basic-lb&lt;/code&gt; called &lt;code&gt;service&lt;/code&gt;.&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="nb"&gt;mkdir &lt;/span&gt;service&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;service&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Inside the &lt;code&gt;service&lt;/code&gt; directory, create a Dockerfile and put the following codes. We will use &lt;code&gt;php:8.1-cli&lt;/code&gt; as the base image.&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="nb"&gt;touch &lt;/span&gt;Dockerfile&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 docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:8.1-cli&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./start.sh

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh", "./start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create the &lt;code&gt;start.sh&lt;/code&gt; scripts.&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

php &lt;span class="nt"&gt;-S&lt;/span&gt; 0.0.0.0:&lt;span class="nv"&gt;$PORT&lt;/span&gt; ./server.php&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, create a file called &lt;code&gt;server.php&lt;/code&gt; to returns a JSON data when user access our service.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'Hello from service %s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SERVICE_ID'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;&lt;br&gt;
In production, you should use something like &lt;code&gt;php-fpm&lt;/code&gt;. But, to simplify this article we just using php built-in web server.&lt;/p&gt;
&lt;h2&gt;
  
  
  Task 3: Creating custom docker network
&lt;/h2&gt;

&lt;p&gt;To be able to connect our things together, we need a docker network. Docker comes with some built-in networks, but we're going to create another one to isolate our services.&lt;/p&gt;

&lt;p&gt;Create a network called &lt;code&gt;docker-basic-lb-network&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create docker-basic-lb-network&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ensure the network is available.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network &lt;span class="nb"&gt;ls&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%2F22didasmt25vhld2moqa.jpeg" 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%2F22didasmt25vhld2moqa.jpeg" alt="result of docker network ls command" width="472" height="132"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Connecting All Things Together
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Build All Images
&lt;/h3&gt;

&lt;p&gt;Move to &lt;code&gt;docker-basic-lb/proxy&lt;/code&gt; and build the proxy image.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; proxy:0.1.0 .&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now move to &lt;code&gt;docker-basic-lb/service&lt;/code&gt; and build the service image.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; service:0.1.0 .&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ensure the images are available.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Running The container
&lt;/h3&gt;

&lt;p&gt;We need to run the service container first because our proxy is depends to the services in order to running correctly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; service-1 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVICE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8000 &lt;span class="nt"&gt;--network&lt;/span&gt; docker-basic-lb-network &lt;span class="nt"&gt;-d&lt;/span&gt; service:0.1.0&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 shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; service-2 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVICE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8001 &lt;span class="nt"&gt;--network&lt;/span&gt; docker-basic-lb-network &lt;span class="nt"&gt;-d&lt;/span&gt; service:0.1.0&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we run two php service with the name of each service is &lt;code&gt;service-1&lt;/code&gt; and &lt;code&gt;service-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's run the proxy container.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; proxy-1 &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 &lt;span class="nt"&gt;--network&lt;/span&gt; docker-basic-lb-network &lt;span class="nt"&gt;-d&lt;/span&gt; proxy:0.1.0&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Open Postman or install it first when you don't have. Hit &lt;code&gt;http://localhost&lt;/code&gt; and you should see something like these...&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%2F8wqsdj89e9c0r05oumr2.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%2F8wqsdj89e9c0r05oumr2.png" alt="Service 1 response" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvn1pkgkiluj1xje8b3wz.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%2Fvn1pkgkiluj1xje8b3wz.png" alt="Service 2 response" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats! Now we have created a load balancer for our services.&lt;/p&gt;

&lt;p&gt;I hope it help and you can enjoy this article. See ya!&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus: The Source Code
&lt;/h2&gt;

&lt;p&gt;Find it &lt;a href="https://github.com/thexdev/devlabs/tree/main/docker-basic-lb" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow my latest experiment here!&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/thexdev" rel="noopener noreferrer"&gt;
        thexdev
      &lt;/a&gt; / &lt;a href="https://github.com/thexdev/devlabs" rel="noopener noreferrer"&gt;
        devlabs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🧙‍♂️  Find my latest experiment here! 🪄
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Welcome, the Alchemist! 🧙‍♂️&lt;/h1&gt;

&lt;/div&gt;

&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🧙‍♂️ The Elder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hohoho, are you lost son? This place is full of curiosity that never end. Don't go away too quick son! Take a look and pick freely as you want, hohoho~&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thexdev/devlabs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>docker</category>
    </item>
  </channel>
</rss>
