<?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: Hazmi Irfan</title>
    <description>The latest articles on DEV Community by Hazmi Irfan (@tehaisperlis).</description>
    <link>https://dev.to/tehaisperlis</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%2F490001%2Fc435eb4a-5977-4180-88c7-82d05438d403.jpeg</url>
      <title>DEV Community: Hazmi Irfan</title>
      <link>https://dev.to/tehaisperlis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tehaisperlis"/>
    <language>en</language>
    <item>
      <title>My thoughts on AI from startup perspective</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Tue, 24 Sep 2024 08:04:50 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/my-thoughts-on-ai-from-startup-perspective-2g6g</link>
      <guid>https://dev.to/tehaisperlis/my-thoughts-on-ai-from-startup-perspective-2g6g</guid>
      <description>&lt;p&gt;I have always wanted to create a startup, but I often feel like I'm a bit late to the party. I was born in the 90s, which means I missed out on the early days of the web, Web 2.0 (social networks), and mobile apps. By the time I was old enough and knew how to code, all the good ideas seemed to be taken. Social networks? Done. To-do lists? Done. Finance apps? Done.&lt;/p&gt;

&lt;p&gt;I don't consider blockchain to be Web 3.0, but that's a whole different topic. Anyway, that's why I was so excited when generative AI came into play. It feels like everything is possible again.&lt;/p&gt;

&lt;p&gt;Now, I spend a lot of my free time building something with generative AI. But after a few attempts, I’ve started to notice a pattern around generative AI that can be discouraging for entrepreneurs like me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Wrapper&lt;/strong&gt;&lt;br&gt;
Let's get the obvious one out of the way. While building my startup, one thing that comes to mind is, if I can do it in ChatGPT, why would I use another app? I quickly realized that whatever startup you build needs to offer more than what ChatGPT can. It doesn't help that OpenAI wants ChatGPT to be its own product. What I’m trying to say is that, as a developer, I don't feel like I’m their top priority—they want ChatGPT to be the default app. For example, I previously built an app that allows users to practice their interviews with AI. Sure, ChatGPT can do that too, but my app offers much more. It not only helps users practice but also provides ratings and feedback, and users can do this multiple times without needing to prompt it like you would in ChatGPT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generative AI is Easy. Too Easy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I mean by "easy" is that someone with coding experience can quickly build something similar to what I want to create. All it takes is a good prompt, and boom—you’re done. Going back to the interview practice app I built, I was one of the first to use generative AI in that space. But now, every month, a new web app pops up offering the same thing. They’re spreading like mushrooms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generative AI Will Not Give You a Competitive Edge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This ties back to the idea that generative AI is too easy to replicate. If your startup relies solely on generative AI for a competitive advantage, it’s not going to work. Established companies can easily copy your idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’re Competing with OpenAI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It also doesn’t help that OpenAI is focused on pushing ChatGPT as its own product. As a developer, I don’t feel like I’m their top priority—they want ChatGPT to become the default app. Whatever OpenAI builds will obviously be more advanced than anything you’re working on, making it tough to compete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, what can you do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Honestly, I’m not entirely sure. One thing I believe is that we need to go back to the basics. What makes a startup successful? It’s not AI—it’s solving a problem that users genuinely care about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, what am I building right now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, I previously worked on an interview practice app, &lt;a href="https://getkasper.app" rel="noopener noreferrer"&gt;Kasper&lt;/a&gt;. However, I’ve recently shifted my focus to a new app, &lt;a href="https://tied.fit" rel="noopener noreferrer"&gt;Tied&lt;/a&gt;, a calorie tracking app. Whether I can make something substantial in the generative AI space remains to be seen, but I don’t regret trying.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>chatgpt</category>
      <category>startup</category>
    </item>
    <item>
      <title>Are you happy with the time for your code to be reviewed?</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Fri, 14 Apr 2023 23:03:51 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/are-you-happy-with-your-code-review-process-48el</link>
      <guid>https://dev.to/tehaisperlis/are-you-happy-with-your-code-review-process-48el</guid>
      <description>&lt;p&gt;This is actually more of a discussion rather than a blog. As a developer I always feel like the review process is slow. Often time it takes days or even weeks to get it reviewed and approved.&lt;/p&gt;

&lt;p&gt;Other than a review reminder is there any other way to improve it? &lt;/p&gt;

&lt;p&gt;I'm interested to know what you guys do to speed up the review process. &lt;/p&gt;

</description>
      <category>github</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Instantly run pull request code on your phone.</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Mon, 15 Nov 2021 10:10:30 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/instantly-run-pull-request-code-on-your-phone-ahk</link>
      <guid>https://dev.to/tehaisperlis/instantly-run-pull-request-code-on-your-phone-ahk</guid>
      <description>&lt;p&gt;Recently I had a problem of trying to show the UI that I have done to my designer. The code need to be merge first an then release to test flight before he got a chance to look at it. If there is any changes, we basically need to go through the flow again which for me is time consuming.&lt;/p&gt;

&lt;p&gt;There has to be a better way and this reminds me of a tool I read on HN but I haven't been able to find the post.&lt;/p&gt;

&lt;p&gt;Basically, one of the staff of a company made an internal tool that would bundle up your RN code when you made a pull request. If you want to run the code, all you need to do is scan the QR code on the PR.&lt;/p&gt;

&lt;p&gt;This makes it faster for you to try and test the code. It would also make it faster for you to take design feedback from the designer. Instead of waiting for it to be release on test flight and play store, they can just scan a QR code and try it instantly.&lt;/p&gt;

&lt;p&gt;One caveat of this method is that it only works on PR that does not require a new native code but I think at some point most app would be mature enough that it won't need to add native code all the time.&lt;/p&gt;

&lt;p&gt;Shopify have something called &lt;a href="https://shopify.engineering/mobile-tophatting-at-shopify-1"&gt;Tophatting&lt;/a&gt; . I'm not sure if this is the post that i saw on HN previously. Unfortunately I don't think they open source it.&lt;/p&gt;

&lt;p&gt;Another one that I can find is &lt;a href="https://github.com/FormidableLabs/appr"&gt;Appr&lt;/a&gt; . Unfortunately it does not work on iOS and even if it does work, it only works on Expo based project.&lt;/p&gt;

&lt;p&gt;I wonder if there is any tool out there that does something similar? Let me know in the comment if you know!&lt;/p&gt;

</description>
      <category>reactnative</category>
    </item>
    <item>
      <title>Should you include your photo on your resume?</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Tue, 16 Mar 2021 07:52:23 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/should-you-include-your-photo-on-your-resume-25f3</link>
      <guid>https://dev.to/tehaisperlis/should-you-include-your-photo-on-your-resume-25f3</guid>
      <description>&lt;p&gt;One of the feature of my website &lt;a href="https://www.logname.dev"&gt;https://www.logname.dev&lt;/a&gt; that I am building right now is that a user will have the ability to generate resume from multiple ready made template.&lt;/p&gt;

&lt;p&gt;This means I need to build the resume template myself and now comes the question, should you include your photo in your resume? &lt;/p&gt;

&lt;p&gt;Personally I have never include my photo on my resume and a quick google would also suggest the same thing. &lt;/p&gt;

&lt;p&gt;Now, having being the interviewer myself and look at multiple resumes, I think the answer should be "it depends".&lt;/p&gt;

&lt;p&gt;Just to be clear, when a resume contain a photo, I don't discriminate(although some people do) but as a human I do judge.&lt;/p&gt;

&lt;p&gt;A resume with a good photo definitely is better than a resume without it.&lt;/p&gt;

&lt;p&gt;BUT, a bad photo is worse than a resume without a photo.&lt;/p&gt;

&lt;p&gt;So what is a bad photo? Well, the one that I keep seeing is a generic passport photo and in my opinion should be omitted. &lt;/p&gt;

&lt;p&gt;Although I don't use the photo to determine whether to hire a person or not, but I do think first impression goes a long way and you should reserve that until the interview itself. &lt;/p&gt;

&lt;p&gt;That is unless you are very good with camera!&lt;/p&gt;

</description>
      <category>resume</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deleted my live production database - Lesson learned</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Sun, 07 Mar 2021 17:40:24 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/lesson-learned-from-deleting-my-live-production-database-9nf</link>
      <guid>https://dev.to/tehaisperlis/lesson-learned-from-deleting-my-live-production-database-9nf</guid>
      <description>&lt;p&gt;You can read more on how I accidentally deleted my live production database for my website &lt;a href="https://www.logname.dev"&gt;https://www.logname.dev&lt;/a&gt; &lt;a href="https://dev.to/tehaisperlis/i-delete-my-live-prod-database-and-have-no-backup-2kp4"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The TLDR version is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted to know how many user registered.&lt;/li&gt;
&lt;li&gt;I don't have admin page so I want to access the database directly&lt;/li&gt;
&lt;li&gt;Instead of connecting to the database I run the delete command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, I decided to compile a list of things that I learn from every comment that I receive. Hopefully you won't repeat the same mistake that I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. You should never connect to a live production database.
&lt;/h2&gt;

&lt;p&gt;I guess this one is pretty obvious and yet this is the main mistake I did. I only want to know how many people registered and I didn't have an admin page back then. &lt;/p&gt;

&lt;p&gt;Instead of creating a simple admin page which only took less than 20 minutes, I instead tried to connect to the live production database and run a query there.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Backup backup backup.
&lt;/h2&gt;

&lt;p&gt;Too be fair to myself, the website had only run for just a day so even if I add an automated backup it might not yet run at that time. &lt;/p&gt;

&lt;p&gt;Still, I only need to click 1 button in the Heroku website to manually back it up and I didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Adding a space before your command will not save it in history.
&lt;/h2&gt;

&lt;p&gt;As far as I know it works in Linux system. If you run a dangerous command, you can start with a space first. This will make sure your command will not be saved in history and you might not accidentally run it again like I did!&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Avoid using confirm flag for dangerous command.
&lt;/h2&gt;

&lt;p&gt;When I deleted my database on purpose the first time, Heroku actually trigger a prompt for confirmation. I can either reply &lt;code&gt;yes&lt;/code&gt; or I need to stop the script and run it again with &lt;code&gt;--confirm&lt;/code&gt; flag. I did the latter. If I deleted it with the first option, when I accidentally run the command again, Heroku will prompt the confirmation flow again, this will give me time to stop the script. Alas, I choose the 2nd flow and the rest is history(literally).&lt;/p&gt;

&lt;p&gt;When I look back, I realize that it wasn't just 1 big mistake but a couple of small mistake that adds up. I may have made some of this mistake in the past but never all of it in the same time. &lt;/p&gt;

&lt;p&gt;Example, I knew it's a mistake connecting to live production database but I did it on my previous project and it was fine back then.&lt;/p&gt;

&lt;p&gt;I also knew you should never perform deletion of database on a command line but I did it before and I was still fine.&lt;/p&gt;

&lt;p&gt;But combining these 2 mistake result in 1 of the biggest mistake I have made so far as a developer. One that I wish I won't repeat in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>sideprojects</category>
      <category>postgres</category>
    </item>
    <item>
      <title>I delete my live prod database and have no backup</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Sat, 20 Feb 2021 17:10:47 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/i-delete-my-live-prod-database-and-have-no-backup-2kp4</link>
      <guid>https://dev.to/tehaisperlis/i-delete-my-live-prod-database-and-have-no-backup-2kp4</guid>
      <description>&lt;p&gt;Welp. That just happen. I just deleted my live production database and I don't have a backup. &lt;/p&gt;

&lt;p&gt;Yesterday I completed my new website &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt; and decided to tell everyone I can about the website(Reddit, Hackernews etc).&lt;/p&gt;

&lt;p&gt;After a day has passed, I want to see how many people register. Me being lazy without admin interface I figured I can login to postgres and query it directly.&lt;/p&gt;

&lt;p&gt;I hosted it on heroku so I can just use this command &lt;code&gt;heroku pg:psql &amp;lt;database-name&amp;gt; --app &amp;lt;app-name&amp;gt;&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;I already run this on terminal so I quickly go to previous history and press enter when I see pg command.&lt;/p&gt;

&lt;p&gt;I forgot that earlier I had run this command &lt;code&gt;heroku pg:reset &amp;lt;database-name&amp;gt; --confirm &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So now my database has successfully reset and I have lost all of my user if any. &lt;/p&gt;

&lt;p&gt;Honestly I am mad as hell right now and I feel ashamed to people who tried to use my website. &lt;/p&gt;

&lt;p&gt;One of the reason I build this website is so that user can rely on this website to maintain their info for a long time because resume is not something u need often but urgent when needed.&lt;/p&gt;

&lt;p&gt;To all who register to give the website a try, I'm really sorry but you need to register and insert the data again but rest assured that this won't happen again.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>heroku</category>
      <category>elixir</category>
      <category>database</category>
    </item>
    <item>
      <title>Implementing Magic-Link</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Thu, 18 Feb 2021 05:20:55 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/implementing-magic-link-1h1b</link>
      <guid>https://dev.to/tehaisperlis/implementing-magic-link-1h1b</guid>
      <description>&lt;p&gt;I wrote a post previously on why I will use Magic Link for the authentication flow. You can read it more &lt;a href="https://dev.to/tehaisperlis/why-i-m-using-magic-link-for-my-website-login-flow-20c5"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The flow is simple, user submit their email and the server will sent a link. User need to click on the link in order to login.&lt;/p&gt;

&lt;p&gt;Some of the requirement needed is&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The link need to be expired after a certain amount of time.&lt;/li&gt;
&lt;li&gt;The link can only be used by the device that requested it. Meaning that if I submit my email on my laptop, I cannot open the link on my phone. It has to be from the same browser.&lt;/li&gt;
&lt;li&gt;The link can only be used once.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For &lt;a href="https://www.logname.com"&gt;Logname&lt;/a&gt;, the link is just &lt;code&gt;https://www.logname.dev/magic_link/login?token=#{token}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The token is in JWT format and the payload contain a unique id of the user as well as a device id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;%{&lt;/span&gt;
 &lt;span class="ss"&gt;unique_id:&lt;/span&gt; &lt;span class="n"&gt;unique_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="ss"&gt;device_id:&lt;/span&gt; &lt;span class="n"&gt;uuid_string&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beside sending the link to the email provided, the server will also response to it with device_id to be stored inside the browser cookie.&lt;/p&gt;

&lt;p&gt;This way, when the user click on the link on the same browser, it will send the payload as well as the device_id cookie, the server will check whether the device_id is the same and if it is, login the user. &lt;/p&gt;

&lt;p&gt;That's it. &lt;/p&gt;

&lt;p&gt;If you would like to try it out. You can register &lt;a href="https://www.logname.dev/users/register"&gt;here&lt;/a&gt; and login &lt;a href="https://www.logname.dev/users/log_in"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jwt</category>
      <category>elixir</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why I'm using Magic Link for my website login flow.</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Fri, 05 Feb 2021 02:33:39 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/why-i-m-using-magic-link-for-my-website-login-flow-20c5</link>
      <guid>https://dev.to/tehaisperlis/why-i-m-using-magic-link-for-my-website-login-flow-20c5</guid>
      <description>&lt;p&gt;Magic Link is a new upcoming authentication flow that allows user to login using only their email. It is kinda like Facebook login but with email instead. &lt;/p&gt;

&lt;p&gt;You might have seen it when using Slack.&lt;/p&gt;

&lt;p&gt;The flow is that you submit your email to the website and it will send a link to your email. Click on it and you are logged in. Just like magic!&lt;/p&gt;

&lt;p&gt;I recently started a new project &lt;a href="https://www.logname.dev"&gt;https://www.logname.dev&lt;/a&gt; and needed to decide on how I am going to let user register and login.&lt;/p&gt;

&lt;p&gt;The easiest way is the normal email and password flow but as a user I hate remembering password for each website I visit.&lt;/p&gt;

&lt;p&gt;Another way is using social login and that is by far the easiest method for the user because it only require 1 click.&lt;/p&gt;

&lt;p&gt;However, after the recent fiasco from Facebook, as a user I am no longer comfortable on using social login anymore. Who knows what data they can get from it.&lt;/p&gt;

&lt;p&gt;So to get the best of both world, I decide to use Magic Link. It is a lot easier than email/password flow and you don't rely on 3rd party service to do it. You also have the added benefit of verifying the user email as they need to use it to login. &lt;/p&gt;

&lt;p&gt;The downside that I can see is that if your email fall under spam, your user might not be aware of it and may think that your login is broken. &lt;/p&gt;

&lt;p&gt;In the next post I'm going to explain more technically on how to implement Magic Link.&lt;/p&gt;

&lt;p&gt;Stay Tuned!&lt;/p&gt;

</description>
      <category>magiclink</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Project #1, 2021 - Logname, a portfolio/resume website for developer.</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Thu, 04 Feb 2021 02:58:14 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/project-1-2021-logname-a-portfolio-resume-website-for-developer-41a5</link>
      <guid>https://dev.to/tehaisperlis/project-1-2021-logname-a-portfolio-resume-website-for-developer-41a5</guid>
      <description>&lt;p&gt;Hi everyone,&lt;/p&gt;

&lt;p&gt;My name is Hazmi and I love to build website on my free time. Although on my previous project I solely focus on building it, this year I want to try something different which is to try and blog as much as I can while building it.&lt;/p&gt;

&lt;p&gt;So, introducing my first project for this year Logname - &lt;a href="https://www.logname.dev"&gt;https://www.logname.dev&lt;/a&gt; - A portfolio/resume website for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why am I building this?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. There is not one website for me to represent my professional developer presence.
&lt;/h3&gt;

&lt;p&gt;As a developer, I always think that you need to have an online presence in order to stand out for better job opportunity. &lt;/p&gt;

&lt;p&gt;Having LinkedIn account is not enough and that is why I also post technical blog here on Dev.to. &lt;/p&gt;

&lt;p&gt;I also have active GitHub account where I pinned the project that best represent my skill set.  &lt;/p&gt;

&lt;p&gt;So as you can see my past experience(LinkedIn), blog posts(Dev) and active projects(GitHub) are all on a separate website. &lt;/p&gt;

&lt;p&gt;If I want to apply for a job I have to provide 3 links. I also need to make sure all 3 are updated accordingly for example if I want to change my profile picture.&lt;/p&gt;

&lt;p&gt;Hopefully if &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt; takes off in the future, I only need to provide 1 url instead of 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. I hate LinkedIn walled garden.
&lt;/h3&gt;

&lt;p&gt;I have to admit I open LinkedIn on a daily basis and it is a great website to build networks.&lt;/p&gt;

&lt;p&gt;But I hate that I cannot easily access my own data using API. I get it if they don't want 3rd party application to abuse the API but at the very least I should be able to get my own data to do what I want. &lt;/p&gt;

&lt;p&gt;I got an idea last time to export my LinkedIn data to reusable format so I can create my own resume but unfortunately that is not allowed.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt;, you can export it into &lt;code&gt;JSON Resume&lt;/code&gt; format so that you are free to do whatever you want with it.&lt;/p&gt;

&lt;p&gt;It is your data after all!.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. I am bad at designing resume.
&lt;/h3&gt;

&lt;p&gt;If I were good at designing I probably will not become a developer in the first place. I know there is a lot of website that can help me build beautiful resume but resume is not a one size fit all solution. &lt;/p&gt;

&lt;p&gt;A resume for developer is different than a resume for a civil engineer. I still need to do some manual work and if I want to use another resume generator? I need to do the manual work again.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt;, you can export it into &lt;code&gt;JSON Resume&lt;/code&gt; format and access over &lt;a href="https://npmsearch.com/?q=jsonresume-theme"&gt;250+ themed resume&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Keeping my resume up to date.
&lt;/h3&gt;

&lt;p&gt;Although most of my info are the same provided I am in the same company, some do change for example my list of projects in the resume. Project in my resume always correspond to my GitHub pinned repository to provide consistency and if that change, I also need to update my resume.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt;, because you can connect your GitHub and Dev account, your resume and portfolio will always be up to date.&lt;/p&gt;

&lt;p&gt;So with all the reason above, I decide to built &lt;a href="https://www.logname.dev"&gt;Logname&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Do check it out and register if you are interested!.&lt;/p&gt;

&lt;p&gt;In the next post I will be explaining why I'm going to be using Magic Link for registration and login and how I will be implementing it technically.&lt;/p&gt;

&lt;p&gt;Stay Tuned!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>elixir</category>
      <category>phoenix</category>
      <category>html</category>
    </item>
    <item>
      <title>Any application that can be written in Javascript, will eventually be written in Javascript</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Thu, 03 Dec 2020 08:09:41 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/any-application-that-can-be-written-in-javascript-will-eventually-be-written-in-javascript-4f49</link>
      <guid>https://dev.to/tehaisperlis/any-application-that-can-be-written-in-javascript-will-eventually-be-written-in-javascript-4f49</guid>
      <description>&lt;p&gt;I was re-reading an old blog &lt;a href="https://blog.codinghorror.com/the-principle-of-least-power/"&gt;The Principle of Least Power&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It became famous for its accurate statement that &lt;code&gt;Any application that can be written in Javascript, will eventually be written in Javascript&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bSRQiV7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o8ju9o4cat0mzfnjtam7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bSRQiV7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o8ju9o4cat0mzfnjtam7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although that alone was funny on how true it is, one comment caught my attention&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sFyLSPAX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mxca131odup6lkg1a4dq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sFyLSPAX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mxca131odup6lkg1a4dq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was commented on 2007, 5 years before Microsoft launch &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt; that have become the De facto language for Javascript programmer. &lt;/p&gt;

&lt;p&gt;The funny thing is, instead of being forced to used it, developer &lt;code&gt;want&lt;/code&gt; to use it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why use Atom?</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Fri, 27 Nov 2020 07:13:14 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/why-use-atom-54cj</link>
      <guid>https://dev.to/tehaisperlis/why-use-atom-54cj</guid>
      <description>&lt;p&gt;Atom is describe as &lt;code&gt;Constants whose values are their own name.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;One of the use of Atom is that it allows you to pattern match.&lt;br&gt;
For example you can pattern match the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle success&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle error&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The code below is okay but when I first tried it, it looks no different to a constant string. &lt;/p&gt;

&lt;p&gt;For example, we can change the code to look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle success&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle error&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of pattern matching an Atom, we pattern match a &lt;code&gt;String&lt;/code&gt; instead. &lt;/p&gt;

&lt;p&gt;The downside of this is that if we want to change &lt;code&gt;ok&lt;/code&gt; to &lt;code&gt;okay&lt;/code&gt; in the future, we need to change it everywhere. However, this is the same problem if we were to use an Atom. &lt;/p&gt;

&lt;p&gt;So why should we use an Atom? Well, after some digging, I found out that Atom value are mapped at runtime. Basically Atom is a global value. &lt;/p&gt;

&lt;p&gt;Why is this important? Lets take a look a the previous code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle success&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="c1"&gt;#handle error&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see the code above, if we were to pattern match using &lt;code&gt;String&lt;/code&gt;, Elixir would need to compare the character 1 by 1. This can obviously become cumbersome.&lt;/p&gt;

&lt;p&gt;If we were to use an Atom instead, Elixir can just compare the pointer/address . We don't have to compare the value 1 by 1 because by default an Atom value is the same. This makes pattern matching much faster.&lt;/p&gt;

&lt;p&gt;Also, the syntax is much nicer :D&lt;/p&gt;

</description>
      <category>elixir</category>
    </item>
    <item>
      <title>The loading anti-pattern.</title>
      <dc:creator>Hazmi Irfan</dc:creator>
      <pubDate>Tue, 17 Nov 2020 07:07:34 +0000</pubDate>
      <link>https://dev.to/tehaisperlis/the-loading-anti-pattern-7jj</link>
      <guid>https://dev.to/tehaisperlis/the-loading-anti-pattern-7jj</guid>
      <description>&lt;p&gt;The loading anti pattern is something that I have experience when I need to fetch a data and then display it.&lt;/p&gt;

&lt;p&gt;Normally when you want to display a data from an API, there are 5 condition that you want to fulfill.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Show initial data. It could be a blank screen.&lt;/li&gt;
&lt;li&gt;Show loading indicator.&lt;/li&gt;
&lt;li&gt;Show the result.&lt;/li&gt;
&lt;li&gt;Show different message if the result is empty.&lt;/li&gt;
&lt;li&gt;Show an error if there is one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's try to built this.&lt;/p&gt;

&lt;p&gt;First the data structure. Most likely it would look like this&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;items&lt;/code&gt; is a list I want to display and &lt;code&gt;isLoading&lt;/code&gt; is a boolean so that I know whether it is loading or not.&lt;/p&gt;

&lt;p&gt;So lets try to display either the loading or the list component 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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&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;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Loading&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&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;So far so good. Now we need to differentiate between the result that have a list and a result that return an empty list. Normally I would do 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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Items&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;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Item&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Typography&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;List is empty&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Typography&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;Items&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;Notice that I use &lt;code&gt;items&lt;/code&gt; as an indicator on whether the result from an API is empty or not. &lt;/p&gt;

&lt;p&gt;This can be a problem because it will show &lt;code&gt;List is empty&lt;/code&gt; initially even when we haven't fetch the data yet.&lt;/p&gt;

&lt;p&gt;One way to solve this is to just set &lt;code&gt;isLoading&lt;/code&gt; to true on the initial data&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;isLoading&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try to handle a case where an API returns an error. First we need to add extra value to the data.&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;isLoading&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;isFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can use &lt;code&gt;isFailure&lt;/code&gt; as an indicator to show the error message.&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;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isFailure&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;/&amp;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="nc"&gt;Box&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;Putting everything together, you have something that 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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;isLoading&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;isFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;=&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="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="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFailure&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;/&amp;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="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&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;List&lt;/span&gt; &lt;span class="o"&gt;=&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="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="nc"&gt;Box&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Loading&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&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;Items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;items&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&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;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Item&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Typography&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;List is empty&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Typography&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;Box&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;So now that I handle all the condition. You might be wondering what is the problem? &lt;/p&gt;

&lt;p&gt;Well, the problem is that I'm trying to describe the state of the data using 3 different value. &lt;code&gt;items&lt;/code&gt;, &lt;code&gt;isLoading&lt;/code&gt; and is &lt;code&gt;isFailure&lt;/code&gt; and this makes your render logic more complex than it should be.&lt;/p&gt;

&lt;p&gt;I have nested &lt;code&gt;if&lt;/code&gt; to cater between different state of the data.&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isFailure&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There can also be an invalid state where both &lt;code&gt;isLoading&lt;/code&gt; and &lt;code&gt;isFailure&lt;/code&gt; can be &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The problem lies with trying to use boolean to describe the state of the data. Boolean can only represent 2 state of the data but we know now that the data can have 4 state. Initial, loading, failure and success. This is why you end up with so many value.&lt;/p&gt;

&lt;p&gt;So how do we fix this? &lt;/p&gt;

&lt;p&gt;I was looking at a video about Elm and one of the talk is about this anti pattern and how to solve them. You can view it &lt;a href="https://www.youtube.com/watch?v=NLcRzOyrH08"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically, what you should do is to have a single value to represent all the possible state of your data. He suggested the state to be &lt;code&gt;notAsked&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;failure&lt;/code&gt; and &lt;code&gt;success&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So now you can describe your data 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;notAsked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notAsked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;failure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failure&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;success&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;notAsked&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;This pattern solve a couple of problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They can no longer be an invalid state.&lt;/li&gt;
&lt;li&gt;There is a single value to represent the state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This can make your render logic a lot more simple.&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;switch&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="nx"&gt;state&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="nx"&gt;notAsked&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;Inital&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;
 &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;loading&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;Loading&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;
 &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;success&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;List&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;
 &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't want to watch a video, you can also read his post &lt;a href="http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html"&gt;How Elm slays a UI antipattern&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Although it is geared towards Elm but I believe it can be implemented elsewhere.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>reactnative</category>
    </item>
  </channel>
</rss>
