<?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: Kehinde Adeleke </title>
    <description>The latest articles on DEV Community by Kehinde Adeleke  (@adeleke5140).</description>
    <link>https://dev.to/adeleke5140</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%2F181039%2Ffc48e3af-20e1-4663-ab34-9828aa10e68a.jpeg</url>
      <title>DEV Community: Kehinde Adeleke </title>
      <link>https://dev.to/adeleke5140</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adeleke5140"/>
    <language>en</language>
    <item>
      <title>Use Precise types instead of String types</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Sat, 19 Aug 2023 19:26:26 +0000</pubDate>
      <link>https://dev.to/adeleke5140/use-precise-types-instead-of-string-types-2f05</link>
      <guid>https://dev.to/adeleke5140/use-precise-types-instead-of-string-types-2f05</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RvTr5__m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54z6786qsa2d9lu73ny1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RvTr5__m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54z6786qsa2d9lu73ny1.png" alt="TS: precise types" width="800" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have all been there. Throwing &lt;code&gt;any&lt;/code&gt; at function parameters and object keys because we couldn't be bothered to type it precisely. I did that for a recent project and it was a cop out.&lt;/p&gt;

&lt;p&gt;The problem is that with &lt;code&gt;any&lt;/code&gt;, we lose many of the benefits typescript offers us. The compile time error checking that can catch hard to detect bugs and also the wonderful code completion.&lt;/p&gt;

&lt;p&gt;Today, I am gonna be discussing precise types and how they can make our code better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Precise Types
&lt;/h2&gt;

&lt;p&gt;A bit of a background. I am currently on Item 33 of Dan Vanderkam's effective typescript.&lt;/p&gt;

&lt;p&gt;Item 33 argues that string types are too broad and open up code to a lot of errors.&lt;/p&gt;

&lt;p&gt;We should consider more precise alternatives that specifies the type of data we expect.&lt;/p&gt;

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

&lt;p&gt;The best way to illustrate this is with an example. &lt;/p&gt;

&lt;p&gt;Suppose, we have a utility function &lt;code&gt;pluck&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The function of &lt;code&gt;pluck&lt;/code&gt; is to pull out all the values for a single field in an object. The objects are members of an array.&lt;/p&gt;

&lt;p&gt;Properly typing the &lt;code&gt;pluck&lt;/code&gt; function can help in making sure that we only use existing keys&lt;br&gt;
that exist in the object.&lt;/p&gt;

&lt;p&gt;To illustrate this properly, I am going to use 4 variants of the &lt;code&gt;pluck&lt;/code&gt; utility function. It would range from untyped to typed. &lt;/p&gt;

&lt;p&gt;Let's go:&lt;/p&gt;

&lt;p&gt;The pluck function without any type is this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 1:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&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;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;Here the function is untyped and while it works at runtime, it opens up a can of errors.&lt;/p&gt;

&lt;p&gt;We aren't sure that the key we use actually exist, which means we might be trying to access a property not present. The return type is also an &lt;code&gt;any[]&lt;/code&gt;. It is practically still valid &lt;code&gt;TS&lt;/code&gt; code but without any benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 2:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&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;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;Here in the second version, it is slightly better but the string type is still too broad. &lt;br&gt;
Remember that this string could also not exists on the object we need to access. The &lt;code&gt;any&lt;/code&gt; type is also problematic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 3:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make the function a generic so that it can infer the specific type of array it is. The type checker complains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--guPLMasK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/adeleke5140/portfolio-v2/main/public/images/pluckV3error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--guPLMasK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/adeleke5140/portfolio-v2/main/public/images/pluckV3error.png" alt="typeError" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We cannot use a string key on an &lt;code&gt;unknown&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;The problem here still persists and this is because string is still broad. It is &lt;strong&gt;stringly typed&lt;/strong&gt;. The return type is also still &lt;code&gt;any[]&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 4:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&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;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are making some progress here. We constrain the key so that it is only an existing key on the object. Typescript infers the return type is not specific enough.&lt;/p&gt;

&lt;p&gt;If you mouse over the function, the return type is &lt;code&gt;T[keyof T][]&lt;/code&gt;&lt;br&gt;
In this case, if there are four keys with values of type &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;string&lt;/code&gt;, the compiler infers the returned &lt;code&gt;array&lt;/code&gt; as a &lt;code&gt;string&lt;/code&gt; or number &lt;code&gt;array&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It can be better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 5:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&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;records&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&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;records&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;record&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;Perfecto. In this final function, we have a generic function with two parameters. &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt; which denotes the object and a key of the object respectively. The second parameter K is a subset of &lt;code&gt;keyof T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We constrain key so that it is only a key that exists on the object.&lt;/p&gt;

&lt;p&gt;Using this variant, we get straightforward autocomplete of the known properties in the object.&lt;/p&gt;

&lt;p&gt;Here is a concrete example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eyZBoCRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7ohisslvhwl2htvgivg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eyZBoCRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7ohisslvhwl2htvgivg.gif" alt="live demo" width="600" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;TS&lt;/code&gt; playground, we see that we get nice autocomplete.&lt;/p&gt;

&lt;p&gt;Check it out in the &lt;a href="https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABABwDYggawDwBUA0iA0ogKYAeUpYAJgM6KakCecwiuAfABQBOpEOL3oAuDgG0AuoSbMRRAJRjc4opKkBvALAAoRIn5QQvJP0HC6AOgC2AQ2R8BQmogC8nA0+HjZkhboBfXV0oZmRSRAAlLxoYMABzXDCI10QAIjojWLg0xAAfdNQYADdSNOCdUPComKTq1O09fURbXlhMsUzeOPj8XWbEWChUUk6oboS+pv1+Eds6UgARWyoxZaopgbNnHrrRmvNYhL3+xCCdXUEwTJbeXjFow72pN0RxU8aB1vaoMTTSGhpTbNIYjP7hXjAARQIGnGakOYLdb7MCkADuiGR3AUwPhh12yT+mRA2VhTQCwM+zW+MA66QAXgCyQNQfs0szmrNSPMlisUejMXzsbjPPjjoTCiUysCKR84bcfn96XE4CM6HRMMwOfpWX8wHBENYhBErrFYAhtZ5EbzVohURisTj5dthATwkSsvAObKdJIANwVK43GmZBipNAYTDcVq8QgAchDUDj-h0Qagop24vCYZQ6Cw0bu8ZdR0SyWTQA"&gt;Live playground&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Typescript offers a lot of quality of life improvement for DX. Even though it can be tempting to throw any all over the place, using precise types benefits far outweighs the trouble of thinking a bit more about our types.&lt;/p&gt;

&lt;p&gt;The effective typescript book is great. Check it out as well &lt;a href="https://effectivetypescript.com/"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Track your interests over time</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Tue, 18 Jul 2023 01:16:06 +0000</pubDate>
      <link>https://dev.to/adeleke5140/track-your-interests-over-time-4b69</link>
      <guid>https://dev.to/adeleke5140/track-your-interests-over-time-4b69</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Interests tracker.&lt;/p&gt;

&lt;p&gt;I built Interests in 8days with no prior knowledge of Refine or MaterialUI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Best Overall Project&lt;/li&gt;
&lt;li&gt;Most Visually Pleasing&lt;/li&gt;
&lt;li&gt;Best Project built using Supabase as the main data provider for the refine app.&lt;/li&gt;
&lt;li&gt;Best Project built using Material UI as the main UI framework for the refine app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://interests.vercel.app/"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d0ElwG-T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z24equpc5wiq94tlcsqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d0ElwG-T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z24equpc5wiq94tlcsqu.png" alt="Welcome Page:" width="800" height="784"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PBU62Do0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hoe08gczeqp9mmr6t29y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PBU62Do0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hoe08gczeqp9mmr6t29y.png" alt="HomePage" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jyRTZS3P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkdazg6shujnlxs6tgef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jyRTZS3P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkdazg6shujnlxs6tgef.png" alt="Interest" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TisZdPKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjigboonezse28o3dsym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TisZdPKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjigboonezse28o3dsym.png" alt="Profile" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Interests is an easy-to-use app for tracking your interests over time. If you have recently watched a fantastic movie, read an exciting book or listened to a lovely song you would like to remember, use &lt;strong&gt;Interests🎉&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Interests helps you save the memories that matter. &lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/adeleke5140/Interests"&gt;Source code&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT&lt;/p&gt;

&lt;h3&gt;
  
  
  Background (What made you decide to build this particular app? What inspired you?)
&lt;/h3&gt;

&lt;p&gt;MMy Go-to tracking app has always been my notes on my iPhone. Finding what I have saved on it takes time and effort. I wanted an easy way to find the interests I enjoyed at a particular time, which is how Interests was born.&lt;/p&gt;

&lt;p&gt;After conducting user research with my friends, I realised that this is something people could find helpful. &lt;/p&gt;

&lt;p&gt;The MVP is ready to use, but the possibilities for what Interests could be is limitless.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it (How did you utilize refine? Did you learn something new along the way? Pick up a new skill?)
&lt;/h3&gt;

&lt;p&gt;This hackathon is my at creating a product using Refine with materialUI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refine&lt;/strong&gt; was used as the frontend framework, &lt;strong&gt;Material UI&lt;/strong&gt; as a UI library and &lt;strong&gt;supabase&lt;/strong&gt; for both auth and as a database&lt;/p&gt;

&lt;p&gt;Refine provides a solid foundation for bootstrapping CRUD apps which I was able to utilize. The authProvider and dataProvider supplied by the swizzle CLI help abstract away the complexity of creating auth and database connection.&lt;/p&gt;

&lt;p&gt;I have used Supabase in the past but have yet to be as integrated as this. Refine helps make working with supabase a breeze. &lt;/p&gt;

&lt;p&gt;I also appreciate the React hooks provided by the team to interact with the supabase client and request the supabase database.&lt;/p&gt;

&lt;p&gt;MaterialUI removed all the complexity of styling and overall layout. Initially, the theming feature was a bit hard to grasp, and I was overwhelmed by the complexity, but after reading through the docs for a couple of days, I got the hang of it.&lt;/p&gt;

&lt;p&gt;The whole stack enabled me to realize this product's vision in 10 days.&lt;/p&gt;

&lt;p&gt;Building this app in Refine has expanded my skillset and my proficiency in technology.&lt;/p&gt;

&lt;p&gt;This is v1, I have started work on improving the design and the overall feel of the app.&lt;/p&gt;

&lt;p&gt;I am also going to conduct more user research in order to add features as well as release a cross platform app in the future.&lt;/p&gt;

&lt;p&gt;Your interests deserve to be remembered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;A couple of resources I found useful include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://refine.dev/docs/"&gt;Refine Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://refine.dev/docs/examples/data-provider/supabase/"&gt;Refine-Supabase Data Provider&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://mui.com/material-ui/getting-started/"&gt;MaterialUI Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://supabase.com/docs/guides/database/overview"&gt;Supabase Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>refinehackathon</category>
      <category>react</category>
      <category>materialui</category>
      <category>supabase</category>
    </item>
    <item>
      <title>How to add Emmet autocomplete for .js files in React</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Sun, 22 May 2022 15:36:31 +0000</pubDate>
      <link>https://dev.to/adeleke5140/how-to-add-emmet-autocomplete-for-js-files-in-react-4bpi</link>
      <guid>https://dev.to/adeleke5140/how-to-add-emmet-autocomplete-for-js-files-in-react-4bpi</guid>
      <description>&lt;p&gt;I recently ran into a problem where Emmet autocomplete would work for files ending with the &lt;code&gt;.jsx&lt;/code&gt; extension but break break for files with the &lt;code&gt;.js&lt;/code&gt; extension. &lt;/p&gt;

&lt;p&gt;To solve it, do the following&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click on the settings icon on the bottom left corner.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PaU5-9Kr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pwa4vf7itaelulrlui3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PaU5-9Kr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pwa4vf7itaelulrlui3d.png" alt="vscode settings icon" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on the document icon to access the settings json file&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--77SQ4FP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7a6n7fjopdqdijw0s3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--77SQ4FP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7a6n7fjopdqdijw0s3r.png" alt="vscode settingsjson icon" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following lines to the end of the settings.json file&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emmet.includeLanguages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascriptreact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emmet.triggerExpansionOnTab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and voila, Your autocomplete should work as expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TpOl2mRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sp3jlb3onu9zn7abz3c8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TpOl2mRQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sp3jlb3onu9zn7abz3c8.gif" alt="emmet autocomplete gif" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React design patterns</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Thu, 19 May 2022 22:05:12 +0000</pubDate>
      <link>https://dev.to/adeleke5140/react-design-patterns-51c6</link>
      <guid>https://dev.to/adeleke5140/react-design-patterns-51c6</guid>
      <description>&lt;p&gt;I am about to take a LinkedIn learning course on React design patterns.&lt;/p&gt;

&lt;p&gt;This blog entry will serve as a public note for others. A lot of people can't access the course since it is tied to a premium subscription. I hope my notes at least help you understand the nitty gritty of writing design patterns in your react applications.&lt;/p&gt;

&lt;p&gt;What are design patterns?&lt;br&gt;
Shaun defines design patterns as &lt;em&gt;effective&lt;/em&gt; solutions to common application development challenges.&lt;/p&gt;

&lt;p&gt;Common Challenges in creating react apps which we would be applying design patterns to include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating reusable layouts&lt;/li&gt;
&lt;li&gt;Reusing complex logic between multiple components&lt;/li&gt;
&lt;li&gt;Working with forms -- specifically why I have a gist on it&lt;/li&gt;
&lt;li&gt;Incorporating functional concepts into our code -- I think this would include not mutating state and stuff.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, we are gonna look at Layout Components.&lt;br&gt;
Layout components are react components that have a primary function of arranging other components on the page.&lt;/p&gt;

&lt;p&gt;Normally, when we create a component, we include the container div and the styles along with it.&lt;br&gt;
an example of that is:&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;styles&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could instead use a layout component that would have the structure and the styles of our app or a specific part of the app and then render children inside of it&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;styles&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-- split the layout styles into their own component&lt;br&gt;
-- display the component itself inside the layout component&lt;/p&gt;

&lt;p&gt;why do we do this?&lt;/p&gt;

&lt;p&gt;It's in a bid to separate the component itself from where it's being displayed on the page.&lt;/p&gt;

&lt;p&gt;In Summary:&lt;br&gt;
The idea of layout components is that our components shouldn't know where they are being displayed.&lt;/p&gt;

&lt;p&gt;Here's a sandbox illustrating it better:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/quizzical-easley-iw4s4n"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Layout components should be written in such a way as to enhance developer experience. Remember, the goal of any software design pattern is not only to solve the problem but to also reduce complexity while doing it.&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>General thoughts: Apollo's GraphQL's Course</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Sun, 15 May 2022 22:39:05 +0000</pubDate>
      <link>https://dev.to/adeleke5140/general-thoughts-apollos-graphqls-course-2nej</link>
      <guid>https://dev.to/adeleke5140/general-thoughts-apollos-graphqls-course-2nej</guid>
      <description>&lt;p&gt;This is a public journal that would include stuff I think are necessary for me to remember. &lt;/p&gt;

&lt;p&gt;Previously I have been tweeting about it, but then Twitter is a private owned platform and anything could happen to my account. &lt;/p&gt;

&lt;p&gt;Now onto the good stuff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Client side, the &lt;code&gt;useQuery&lt;/code&gt; hook returns an object with 3 useful properties. They are destructured. The first, loading, indicates whether the query has completed and results have been returned. The second, error is an object that contains any errors that the operation has thrown. The third, data contains the results of the query after it has completed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To set variables in our Query, we declare them in the second parameter of the &lt;code&gt;useQuery&lt;/code&gt; hook, inside the options object.&lt;/p&gt;

&lt;p&gt;Code Example using React JS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gql&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;@apollo/client&lt;/span&gt;&lt;span class="dl"&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;GET_TRACK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query getTrack($trackId: ID!) {
    track(id: $trackId) {
      id
      title
      author {
        id
        name
        photo
      }
      thumbnail
      length
      modulesCount
      numberOfViews
      modules {
        id
        title
        length
      }
      description
    }
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Track&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_TRACK&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;
       &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;//render UI&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;ol&gt;
&lt;li&gt;I had to create a schema for the module type for a track, get the data from the dataSource and structure the resolver to return the required field.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd say the hardest part was the resolver but with some thinking, I was able to figure it out.&lt;/p&gt;

&lt;p&gt;What I learned is that: Your resolver function should follow your schema defined. Not just willy nilly stuff.&lt;/p&gt;

&lt;p&gt;First the schema:&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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the title of the particular module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the url of the particular module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;videoUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the content of the particular module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then defining the Query that would return the required module when supplied with an argument&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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Query to get tracks array for the homepage grid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;tracksForHome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Track&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a track id would return a details about a specific track&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Track&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a module would return details about a specific module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt;&lt;span class="o"&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 dataSource for the current application is a RESTAPI so I had to use a method to get the module from that.&lt;/p&gt;

&lt;p&gt;I did that by writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nf"&gt;getModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleId&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="k"&gt;this&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="s2"&gt;`module/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;moduleId&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finally the resolver. This part got me so confused because of&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the parent parameter&lt;/li&gt;
&lt;li&gt;the args parameter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I still haven't gotten the grasp of the arguments resolver functions need so it took me a bit to think through my Schema and how the Query is going to be structured.&lt;/p&gt;

&lt;p&gt;After that, I solved it and wrote the following resolver function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trackAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//nested in a query parent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I just read about Mutations and how they can serve as entry points into our GraphQL Api especially if we need to write data to our server.&lt;/p&gt;

&lt;p&gt;A fill in the gap exercise on the Apollo website resulted in this helpful paragraph.&lt;/p&gt;

&lt;p&gt;"Queries and Mutations are both types of GraphQL &lt;code&gt;operations&lt;/code&gt;. Queries are &lt;code&gt;read&lt;/code&gt; operations that always &lt;code&gt;retrieve&lt;/code&gt; data. Mutations are &lt;code&gt;write&lt;/code&gt; operations that always &lt;code&gt;modify&lt;/code&gt; data. Similar to &lt;code&gt;Query&lt;/code&gt; fields, fields of the &lt;code&gt;Mutation&lt;/code&gt; type are also &lt;code&gt;entry points&lt;/code&gt; into a GraphQL API."&lt;/p&gt;

&lt;p&gt;Mutations can be easy or complex depending on the return value required and the fields being modified.&lt;/p&gt;

&lt;p&gt;For example, a simple mutation can just have one return value. 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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;addSpaceCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SpaceCat&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This is because once we call the addSpaceCat mutation, we want the client to get the updated value of the SpaceCat we just mutated.&lt;/p&gt;

&lt;p&gt;Sometimes, though, one mutation should return multiple values.&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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;assignMission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;missionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spaceCatId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//what should we return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and so because we need to return both, we need to create a new type. This type would include&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;code&lt;/code&gt;: an &lt;code&gt;Int&lt;/code&gt; that refers to the status of the response similar to an HTTP status code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;success&lt;/code&gt;: a &lt;code&gt;Boolean&lt;/code&gt; flag that indicates whether all the updates the mutation was responsible for succedded.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: a &lt;code&gt;String&lt;/code&gt; to display information about the result of the mutation on the client side. This is useful for us if the mutation is only, well partially successful and a generic error message won't tell the whole story.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;with that, we then create a new type for our mutation respose.&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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AssignMissionResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;spacecat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Spacecat&lt;/span&gt;
   &lt;span class="nx"&gt;mission&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Mission&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regarding GraphQL Mutation:&lt;/p&gt;

&lt;p&gt;We use hooks to send requests to our GraphQL API from a React client. To send a mutation, we use the &lt;code&gt;useMutation&lt;/code&gt; hook. This returns an &lt;code&gt;array&lt;/code&gt; where the first element is the &lt;code&gt;mutate function&lt;/code&gt; used to trigger the mutation. The second element is an object with more information about the mutation, such as &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt;. This hook takes in a &lt;code&gt;GraphQL operation&lt;/code&gt; as the first parameter. It also takes in an &lt;code&gt;options&lt;/code&gt; object as the second parameter, where properties like &lt;code&gt;variables&lt;/code&gt; are set.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Fix error with openai in your nodeJS app</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Thu, 12 May 2022 00:04:53 +0000</pubDate>
      <link>https://dev.to/adeleke5140/how-to-fix-error-with-openai-in-your-nodejs-app-5en2</link>
      <guid>https://dev.to/adeleke5140/how-to-fix-error-with-openai-in-your-nodejs-app-5en2</guid>
      <description>&lt;p&gt;I was trying out openAI's api when I came across this error.&lt;/p&gt;

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

&lt;p&gt;It was quite annoying. To solve it, you add the &lt;code&gt;"type": "module"&lt;/code&gt; to your package.json file.&lt;/p&gt;

&lt;p&gt;If you don't have a package.json file, use &lt;code&gt;npm init -y"&lt;/code&gt; to create one.&lt;/p&gt;

&lt;p&gt;With that, you should have this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggvolljuzmhpmlbedobu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggvolljuzmhpmlbedobu.png" alt="type module"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;which should solve it.&lt;/p&gt;

&lt;p&gt;but...something else might come up. Since you need your API key in a .env file to access the api, you would need to import the dotenv package. &lt;/p&gt;

&lt;p&gt;after installing with npm or yarn, I used the require keyword to import it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require('dotenv').config();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For some reason, that seems to throw another error:&lt;/p&gt;

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

&lt;p&gt;It was very frustrating and stack overflow didn't seem to have a direct answer.&lt;/p&gt;

&lt;p&gt;To solve it, change require to a normal import statement, &lt;/p&gt;

&lt;p&gt;in this case it would be, &lt;code&gt;import dotenv from 'dotenv/config'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;the final code looks like this:&lt;/p&gt;

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

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

&lt;p&gt;with that, you are done.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Understand Metamask: the basics.</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Wed, 30 Mar 2022 00:33:01 +0000</pubDate>
      <link>https://dev.to/adeleke5140/understanding-metamask-the-basics-2bg0</link>
      <guid>https://dev.to/adeleke5140/understanding-metamask-the-basics-2bg0</guid>
      <description>&lt;p&gt;The browser-based wallet Metamask is a gateway to exploring Dapps and the world of Crypto. You need a wallet to explore innovation which includes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://ethereum.org/en/defi/"&gt;DeFi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ethereum.org/en/nft/#main-content"&gt;NFTs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ethereum.org/en/dao/#main-content"&gt;DAOs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yet, the web interface can be daunting to wrap one's head around. In addition, it can be confusing if you haven't used an extension before, especially for carrying out financial transactions.&lt;/p&gt;

&lt;p&gt;In this article, I aim to simplify the Metamask web interface so that you can understand what is going on. &lt;/p&gt;

&lt;p&gt;This tutorial is not an in-depth tutorial. It will only break down the main features of the Metamask Interface.&lt;/p&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

&lt;p&gt;Click the extension in the top bar of your browser. It reveals a mini-window similar to the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S5JrAYmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7hq28olumecysi0pw2et.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S5JrAYmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7hq28olumecysi0pw2et.png" alt="first page of metamask" width="446" height="736"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a look at the key features.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Connected network
&lt;/h2&gt;

&lt;p&gt;By default, the network Metamask shows is Ethereum Mainnet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NaxRqGTN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o29exzvwv8drb25owka6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NaxRqGTN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o29exzvwv8drb25owka6.png" alt="Metamask network: Ethereum mainnet" width="382" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Ethereum network is the leading network for smart contracts, Defi, NFTS, and DAOs. Therefore, if you plan on transacting on the Ethereum network, you do not need to change this.&lt;/p&gt;

&lt;p&gt;A developer working on a project on a different network like Polygon will need to change this. &lt;/p&gt;

&lt;p&gt;A regular user might or might not need to change it. &lt;/p&gt;

&lt;p&gt;For the scope of this tutorial, we will leave it as is. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Account Information
&lt;/h2&gt;

&lt;p&gt;Beneath the network section lies another section. The highlighted circle is the account Info.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IV9Sple8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0an9acrjkga6ad75cxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IV9Sple8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0an9acrjkga6ad75cxd.png" alt="account info" width="395" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accounts can have custom names that you set during the initial setup. For example, I have it set as Account 1.&lt;/p&gt;

&lt;p&gt;Look a bit closer. You can see a set of random characters. For example, it is "0xAB*...359b" in the image above.&lt;/p&gt;

&lt;p&gt;The set of characters is your wallet address. The wallet address is helpful for several tasks. The tasks include the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receiving Eth&lt;/li&gt;
&lt;li&gt;Minting NFTs&lt;/li&gt;
&lt;li&gt;Using Defi Protocols etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hover and Click the account info box to copy your address to the clipboard. The account info helps receive funds from others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--The5JrFf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzrb16p96tqm2dt96jea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--The5JrFf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzrb16p96tqm2dt96jea.png" alt="Copy wallet address" width="439" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Connection Status
&lt;/h2&gt;

&lt;p&gt;The connection status sits to the left of the Account Info section. It verifies your connection to a Decentralized application.&lt;/p&gt;

&lt;p&gt;Decentralized applications have a "Connect wallet" feature. Once connected, the icon changes from "Not connected" to "Connected."&lt;/p&gt;

&lt;p&gt;In the image below, the user is unconnected. The icon is grey with the text "Not connected" next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H2U_nwUu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6ljwwdx0mj717z0ffrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H2U_nwUu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6ljwwdx0mj717z0ffrk.png" alt="Metamask connection status: not connected" width="410" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once connected to a Dapp, the icon and text change. It changes to a green icon with the text "Connected" next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOBPlWA1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj13q2h60v6hilo7ee4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOBPlWA1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj13q2h60v6hilo7ee4a.png" alt="Metamask connection status: connected" width="401" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Account Balance
&lt;/h2&gt;

&lt;p&gt;It's a wallet, and a wallet should show much funds is present.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---6EYjy9r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f7vcalyfcgwdm7kuio8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---6EYjy9r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f7vcalyfcgwdm7kuio8z.png" alt="Metamask balance" width="396" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The account balance section gives the amount of Eth and the equivalent value in USD. In the settings, you can modify the type of currency it shows. By default, it shows the ETH balance as the principal balance. Beneath that is the equivalent value in USD.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Financial services
&lt;/h2&gt;

&lt;p&gt;Metamask is a wallet that provides three essential services. The services include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buying Crypto.&lt;/li&gt;
&lt;li&gt;Sending Crypto.&lt;/li&gt;
&lt;li&gt;Swapping Crypto&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The image below shows these services and the icons:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U12440mn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcvtybmd1e3lbu9im92w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U12440mn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcvtybmd1e3lbu9im92w.png" alt="benefits of metamask" width="396" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buying Crypto:
Let's explore what these features are:
Click on the Buy icon to buy some Eth. Clicking the icon shows services that offer you ETH for fiat currency.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Get some Eth with Wyre. You can get Eth directly into your account with your debit card.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uGyMgH8V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdwikd5ont5j5jc5ng21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uGyMgH8V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdwikd5ont5j5jc5ng21.png" alt="deposit eth through wyre" width="441" height="737"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Transat is an alternative method. It comes with the added benefit of using a bank transfer if you do not have a card.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WRn-LWoP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjhlnnan3f080x7mrz8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WRn-LWoP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjhlnnan3f080x7mrz8i.png" alt="deposit eth through transak" width="446" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last option is a direct deposit. If you've both some Eth on an exchange like Binance, Kucoin, FTX, Buy coins, e.t.c, you can copy your address from the account info and send the ETH to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tncep6jo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeu63bavmepqwlkwdlle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tncep6jo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeu63bavmepqwlkwdlle.png" alt="direct deposit eth" width="439" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The methods above for funding your wallet all have their pros and cons. However, it is not within the scope of this article to discuss that.&lt;/p&gt;

&lt;p&gt;Use whatever means is convenient and intuitive to you.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sending Crypto:
The send crypto feature is for transferring tokens from one wallet to another. The address could be yours, a friend's, or an exchange.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Always endeavor to double-check the address. Transactions carried out on blockchain networks are immutable, so they cannot be reversed once carried out and confirmed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Swap Crypto:
You can swap one currency for the other. However, swapping a currency on the Ethereum network is only works if the coin is on the Ethereum network. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that: You will have to pay network fees which cost quite a bit on the Ethereum network.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Available Assets
&lt;/h2&gt;

&lt;p&gt;Metamask provides the feature of interaction with other Crypto apart from the native Eth token.&lt;/p&gt;

&lt;p&gt;The Process of adding this to display can be daunting. Yet, it is helpful to know that you can.&lt;/p&gt;

&lt;p&gt;In the image below, I have added the Bzz token. I can give out my address and receive BZZ through it. Receiving BZZ works because the BZZ token utilizes the Ethereum blockchain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G6jE20I6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz8piy6kakxt7tyw622w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G6jE20I6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz8piy6kakxt7tyw622w.png" alt="assets in metamask" width="411" height="678"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are cases where you need to switch to a different network for specific Dapps. One example of that is the Polygon network to use the MATIC token.&lt;/p&gt;

&lt;p&gt;This section includes the added benefit of showing the amount of tokens present.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Activity
&lt;/h2&gt;

&lt;p&gt;The last feature is the activity tab.&lt;/p&gt;

&lt;p&gt;The activity tab shows all transactions you have carried out through your wallet. &lt;/p&gt;

&lt;p&gt;Let's explore the two transactions in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MXAyI96J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4wsmnutej0c30cuyp7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MXAyI96J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4wsmnutej0c30cuyp7g.png" alt="asset activity in metamask" width="393" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first is an NFT mint. It has the title Mint. On the 25th of March, it occurred on a website titled &lt;a href="http://www.721.so"&gt;www.721.so&lt;/a&gt;. There, I minted an NFT free of charge.&lt;/p&gt;

&lt;p&gt;I can recognize that it is free because it cost me 0ETH.&lt;/p&gt;

&lt;p&gt;The second is a transfer. In this transfer of tokens, I am the recipient. The title Receive indicates that. On the 25th of March, it occurred from an address with the characters: "0x153...c170". &lt;/p&gt;

&lt;p&gt;The section adjacent to that shows the amount of Eth I received.&lt;/p&gt;

&lt;p&gt;The activity tab fills up as you engage with more apps built on the Ethereum network. However, it is not limited to apps. Any outflow or inflow of funds is also registered and documented.&lt;/p&gt;

&lt;p&gt;It helps provide an accessible overview of what happens and where.&lt;/p&gt;

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

&lt;p&gt;The following features explored above are all you need to start with Metamask.&lt;/p&gt;

&lt;p&gt;There are more in-depth features of using the wallet. We will explore this in a different article.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>metamask</category>
    </item>
    <item>
      <title>How to setup a Metamask account.</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Mon, 28 Mar 2022 01:15:55 +0000</pubDate>
      <link>https://dev.to/adeleke5140/how-to-setup-a-metamask-account-50f9</link>
      <guid>https://dev.to/adeleke5140/how-to-setup-a-metamask-account-50f9</guid>
      <description>&lt;p&gt;Metamask is an application you probably have heard of, maybe from friends or family or twitter. It is a browser-based crypto wallet that provides a "gateway to blockchain apps." Metamask helps users send and receive cryptocurrencies and explore &lt;a href="https://ethereum.org/en/developers/docs/dapps/"&gt;decentralized applications(Dapps)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The definition above is a simplified definition of it. If you want to learn more, visit &lt;a href="https://metamask.io/"&gt;this link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Metamask is very useful if you need to create an account to try out a decentralized application or mint an NFT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a Metamask account
&lt;/h2&gt;

&lt;p&gt;Follow the steps below to create a Metamask account to mint that favorite NFT you love.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Download Metamask:&lt;/strong&gt;&lt;br&gt;
Metamask is a browser based wallet. You get it by installing a browser extension to your browser of choice. The official Metamask website is located at &lt;a href="https://metamask.io"&gt;https://metamask.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The landing page shows this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VE_XOCjH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ud4jk12txemth2lgdz8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VE_XOCjH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ud4jk12txemth2lgdz8d.png" alt="the metamask.io landing page" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the Download now button:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i5cvL55U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppxlc8x8qc31pwykpwoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i5cvL55U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppxlc8x8qc31pwykpwoj.png" alt="the download page for Metamask extension" width="800" height="502"&gt;&lt;/a&gt;&lt;br&gt;
I am currently using Brave browser, which uses the same Chromium engine as Google chrome. Hence, the "Install Metamask for Chrome" button.&lt;/p&gt;

&lt;p&gt;Once installed, the extension logo resides on the top bar, adjacent to the search field on most popular browsers. Here is where it sits in the brave browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9TzlraG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhfzlwerp9mh0izkrvzs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9TzlraG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhfzlwerp9mh0izkrvzs.png" alt="location of Metamask extension in brave browser" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create a Metamask account:&lt;/strong&gt;&lt;br&gt;
Click on the browser extension. The screen below pops up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8nGN2LEB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32e88wkrekk2xfbwubxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8nGN2LEB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32e88wkrekk2xfbwubxp.png" alt="Metamask get started" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;click Get started.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ccd3OlLg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ix69l85gfhwc860fikoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccd3OlLg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ix69l85gfhwc860fikoi.png" alt="get started with metamask" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I assume you are a new user. With that, click on create a wallet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pN4P2AmC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ut7uz2mexmfausoojw9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pN4P2AmC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ut7uz2mexmfausoojw9u.png" alt="creating a wallet" width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read through the terms and conditions of the extensions. Then, click on "I agree." The next page shows two fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LyBNXRML--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nn60g0bv7zf1k5ltq4dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LyBNXRML--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nn60g0bv7zf1k5ltq4dy.png" alt="create a password" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A password and confirm password fields. The password you create helps to keep your account secured from unauthorized access.&lt;/p&gt;

&lt;p&gt;You can make secure passwords for your apps with a password manager. A free, open-source example is &lt;a href="https://bitwarden.com/"&gt;Bitwarden&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that is set up. Metamask shows a helpful video for keeping your account secure. Watching the video is the most crucial step in creating your account. Please, pay attention to this detail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--827CbFe1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzdqb70fglg4jo3nmxez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--827CbFe1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzdqb70fglg4jo3nmxez.png" alt="understanding what a seed phrase is" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After reading through, click next. If you just skimmed through the content, here is a summary. Your secret phrase is a master key to all of your funds. &lt;/p&gt;

&lt;p&gt;It would help if you did not give it to anyone unless people you trust very much. It would be best to keep it secure in either a piece of paper in multiple places or a password manager. I use the latter as it is more flexible.&lt;/p&gt;

&lt;p&gt;Click Next.&lt;br&gt;
The seed phrase sits hidden behind a lock button. Once you are sure no one is peeking behind your shoulders, click the button to unhide your seed phrase.&lt;/p&gt;

&lt;p&gt;Next, you must take note of it and store it in a self place. Remember, you are in charge of the security of your wallet.&lt;/p&gt;

&lt;p&gt;Save your seed phrase somewhere and follow the required steps. That should do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qKGIVGZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u86jghw4zbh4qvb5lowe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qKGIVGZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u86jghw4zbh4qvb5lowe.png" alt="congratulations screen of metamask" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voila! Congratulations. You are ready for the next stage of the internet.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>metamask</category>
    </item>
    <item>
      <title>An Appreciation of ReactJS</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Tue, 08 Mar 2022 13:23:38 +0000</pubDate>
      <link>https://dev.to/adeleke5140/an-appreciation-of-reactjs-1jg5</link>
      <guid>https://dev.to/adeleke5140/an-appreciation-of-reactjs-1jg5</guid>
      <description>&lt;p&gt;Web technologies evolve quickly. Before you say: Jack and Jill went... boom, three new JS frameworks have been released. For the web developer, it means that we are currently flooded with options for building web applications. Sometimes, this leads to fatigue. Yes, framework fatigue is a real thing. &lt;/p&gt;

&lt;p&gt;The amount of choice a developer has to make is used as an argument against the JS ecosystem. There is some merit in that. I do believe though that Frameworks have considerable improved the Developer experience.&lt;/p&gt;

&lt;p&gt;I will be discussing ReactJS and its ecosystem and how it has made building JS applications easier.&lt;/p&gt;

&lt;p&gt;N.B: I am a beginner to ReactJS. I have built a couple of landing pages with it. Right now, I'm working on a fun little country facts app with APIs. I don't purport to know all there is to know about the workings of the framework. Everything I share here is from my personal experiences from using both React and vanilla JS to build apps.&lt;/p&gt;

&lt;p&gt;ReactJS component-based architecture isn't unique. Every other framework from Vue and Angular both uses that same type. I am not as experienced in either of those so I won't be talking about them.&lt;/p&gt;

&lt;p&gt;I appreciate React. I enjoy using React. That would shock a lot of beginners because the narrative in the JS community is that, React isn't the best for newbies. There is JSX to grapple with, CSS-in-JS, how exactly state and props work, etc. I did face these issues when I first got started but now I recognize why I did.&lt;/p&gt;

&lt;p&gt;My Javascript was very low level. I knew what ES6 was but never used it in building. I just couldn't think in React. That therein lied the problem.&lt;/p&gt;

&lt;p&gt;You see, thinking in React requires a departure from vanilla JS imperative mode of DOM manipulation. Sure you can write declarative code in vanillaJS but I never tried it, probably because it just seemed unnecessarily complicated. What React offered though was something radically fun. Building and updating the DOM had never been easier.&lt;/p&gt;

&lt;p&gt;Let's take one example: I tried building a form for user feedback collection. I generated the HTML elements and CSS both all in JS and well...it was a mess. In my defense, I did leave enough comments to guide whoever was gonna use the codebase later on. It is not an effective way to build apps.&lt;/p&gt;

&lt;p&gt;A single change in a property declaration for a button element, caused the whole page to refresh. I can't sufficiently explain my frustration every time it happened. This is where React's shadow DOM spoiled me. &lt;/p&gt;

&lt;p&gt;A single change in one section -- say a component -- needn't rerender the whole app. The shadow DOM just updates the parts of the DOM necessary to see changes. "This is...magic" I uttered. Sure, I could be overreacting. But the thing is, I had never experienced such ease in building apps. It increased my workflow and made sure I spent more time thinking in React.&lt;/p&gt;

&lt;p&gt;Let's explore that a bit as well. I think the component-based structure of the react is a major plus. It forces you:&lt;br&gt;
 to think of reusable components,&lt;br&gt;
 what data would be required in my case &lt;br&gt;
how it all fits into the whole-- the app itself. &lt;/p&gt;

&lt;p&gt;When I got started with a Tweet component I was making, I had to let others know of this joy.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;It was pretty exciting to make.&lt;/p&gt;

&lt;p&gt;The final result of that was this:&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;I am still learning a lot about ReactJS. I recently just learned about the useState and useEffect hook. They are pretty nifty features react provides to manage state and side effects.&lt;/p&gt;

&lt;p&gt;I like React. Sometimes, I get frustrated when stuff doesn't work as I expect it to, I believe it's a web technology I will enjoy as I keep building and using it.&lt;/p&gt;

&lt;p&gt;Interested, check out the. They are amazing.&lt;a href="https://beta.reactjs.org/"&gt;new React docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to show Image Preview from Input element.</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Sat, 12 Feb 2022 18:34:34 +0000</pubDate>
      <link>https://dev.to/adeleke5140/how-to-show-image-preview-from-input-element-4eo8</link>
      <guid>https://dev.to/adeleke5140/how-to-show-image-preview-from-input-element-4eo8</guid>
      <description>&lt;p&gt;Ever wanted to style the input with &lt;code&gt;type="file"&lt;/code&gt; form control, and have a mini image preview in addition to that, you are in the right place.&lt;/p&gt;

&lt;p&gt;Today, we will walk through how to make that specific input element accessible and beautiful.&lt;/p&gt;

&lt;p&gt;Before that, a brief introduction:&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: Forms Ubiquity
&lt;/h2&gt;

&lt;p&gt;Forms are one of the key components of the web. They are everywhere. If you want to login or sign up for a service, you interact with a form. If you need to provide feedback for a product, your data is collected with a form.&lt;/p&gt;

&lt;p&gt;It is therefore paramount that as users and designers of forms, we should work towards making sure, they aren't a hassle to fill in. They are easy to understand, and the user leaves with the reassurance that they have filled in the appropriate details.&lt;/p&gt;

&lt;p&gt;If you need a deep dive into how to create accessible forms, &lt;a href="https://web.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;web.dev&lt;/strong&gt;&lt;/a&gt; by Google developers has a wonderful module on forms. You can access it by clicking &lt;a href="https://web.dev/learn/forms/" rel="noopener noreferrer"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For today, we are going to be working with the input element. Specifically, the input element of &lt;code&gt;type="file"&lt;/code&gt;. This input element is used to help users select and upload files from their devices. It could be mobile or desktop.&lt;/p&gt;

&lt;p&gt;One issue with this input form control though is: it is very difficult to style. The default look of it when you create an input element is this:&lt;/p&gt;

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

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file&amp;gt;&amp;lt;/input&amp;gt;


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

&lt;/div&gt;

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

&lt;p&gt;It is easy to understand. Yet, not exactly how we want it to be. &lt;/p&gt;

&lt;p&gt;We want the label styles to look like a button and also show an image Preview. Let's get right on to it.&lt;/p&gt;

&lt;p&gt;The whole project can be found on JSFiddle. If you are interested in seeing the final result, click the &lt;a href="https://jsfiddle.net/f1bc7vsy/35/" rel="noopener noreferrer"&gt;&lt;strong&gt;Link to JSFiddle playground&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you do want to code along from scratch, let's get started.&lt;/p&gt;

&lt;p&gt;This project is going to be divided into three sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Markup&lt;/li&gt;
&lt;li&gt;The Styling&lt;/li&gt;
&lt;li&gt;Interactivity with JavaScript&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Markup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Markup is the HTML we have to work with. The required elements we need are:&lt;/p&gt;

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

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"file-upload"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Select an Image&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"file-upload"&lt;/span&gt; 
  &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;accepts=&lt;/span&gt;&lt;span class="s"&gt;".jpg, .jpeg, .png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"preview"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"file-preview"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Let's look at what this markup is all about. We create a div with a class of Container. This div is going to contain both our form control -- the  input of type="file" -- and the image element we need to display as a preview.&lt;/p&gt;

&lt;p&gt;Next is the label for the input element. For accessibility, input fields should always have a label that describes the form control. Here the label has a for attribute of file which corresponds to the id of the input element. &lt;/p&gt;

&lt;p&gt;Just think of it this way, the label for attribute tells us what form it is linked to. The form it is linked to will have the same value in its id.&lt;/p&gt;

&lt;p&gt;so label for="file" tells screen readers that it is related to the input id="file". Remember that  attributes values are case sensitive. file is not the same as File. that could potentially trip you up so be wary of it.&lt;/p&gt;

&lt;p&gt;Next we have our form control with a name and an id. We add the accepts attribute that tells us what can be uploaded. Here it is delimited to files that have the &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.jpeg&lt;/code&gt; or .png extension. That attribute is optional and you can safely take it out.&lt;/p&gt;

&lt;p&gt;The next line of code is our container with the class of preview. This container will hold our image element inside of it. The image element doesn't have a &lt;code&gt;src&lt;/code&gt; nor &lt;code&gt;alt&lt;/code&gt; attribute...yet. It has an id. We are going to insert the &lt;code&gt;src&lt;/code&gt; and alt attribute with the help of JavaScript. &lt;/p&gt;

&lt;p&gt;Once you have all that done, you should have this:&lt;/p&gt;

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

&lt;p&gt;We have our basic form control. Next, onto styling.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Styling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CSS is always fun to write. We are going to be doing quite a lot to transform our meh input form control to an attractive button.&lt;br&gt;
Let's get started:&lt;/p&gt;

&lt;p&gt;First, we give our body element, a height of 100vh&lt;/p&gt;

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

&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&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;Next, we style our container.&lt;/p&gt;

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

&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We give the container, a height and width property. Next we add the &lt;code&gt;display: flex&lt;/code&gt; property to align the children of the container to the center of it. The &lt;code&gt;flex-direction&lt;/code&gt; changes the orientation of the children from row to column&lt;/p&gt;

&lt;p&gt;With that, we should have this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaoctrnu06f7i2ul0bgl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaoctrnu06f7i2ul0bgl.png" alt="basic form control styling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to style the form control. Input fields of type file are not exactly easy to style so we are going to style the label element instead. Remember, the for attribute we added before. Now it is going to come in handy. Because we set a for attribute on the label element, we can visually hide the input element from the screen and yet still trigger the corresponding action. Let's see that in code&lt;/p&gt;

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

&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;hotpink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Avenir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;11px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.19&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;box-shadow&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;0.25s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We have basic button styles. We give it a &lt;code&gt;background&lt;/code&gt; of &lt;code&gt;hotpink&lt;/code&gt; -- because &lt;code&gt;hotpink&lt;/code&gt; is the best color -- &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;border-radius&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;box-shadow&lt;/code&gt; is to make our button have this push down effect. We would get to that soon. the &lt;code&gt;active pseudo-class&lt;/code&gt; is added to the &lt;code&gt;label&lt;/code&gt; element in order to remove the &lt;code&gt;box-shadow&lt;/code&gt; when it is active. &lt;/p&gt;

&lt;p&gt;Quick Info on the active pseudoclass by &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:active" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user. When using a mouse, "activation" typically starts when the user presses down the primary mouse button.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With all that added, we should have this:&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;input&lt;/code&gt; element is still present. We can style this by either using the &lt;code&gt;opacity&lt;/code&gt; property or making it non-visible. The &lt;code&gt;opacity&lt;/code&gt; property is recommended because, according to MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: opacity is used to hide the file input instead of visibility: hidden or display: none, because assistive technology interprets the latter two styles to mean the file input isn't interactive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We still want assistive technologies to know that we can interact with the form control. The way I did it was to just make the &lt;code&gt;input&lt;/code&gt; element miniscule. Here's the code:&lt;/p&gt;

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

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;#file&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&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;which gives us:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffk2vmmnqg4fugqq1ky62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffk2vmmnqg4fugqq1ky62.png" alt="button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it is in motion:&lt;/p&gt;

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

&lt;p&gt;We have that nice click effect.&lt;/p&gt;

&lt;p&gt;For the image element, we can hide it for now. You can do that by using the line of code below:&lt;/p&gt;

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

&lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.preview&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&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;That is all for our button styles and our image element.&lt;br&gt;
We are going to style the container with the class of preview for a couple of reasons. First, we want a &lt;code&gt;margin&lt;/code&gt; to separate our image from the button. We also wouldn't want any jarring layout shift so we set an extrinsic size with the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;position&lt;/code&gt; property is to align it along the left margin of the button.&lt;/p&gt;

&lt;p&gt;All that's left to add is JavaScript to display the image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactivity with JavaScript.
&lt;/h3&gt;

&lt;p&gt;The first thing to do is to get the &lt;code&gt;input&lt;/code&gt; element from the DOM tree and assigning it to a variable. We do that by typing this:&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;uploadButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type="file"]&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;Next, we add an EventListener to the input element, we listen for a change event because a change event signifies that a file has been added, followed by an arrow function with the event object.&lt;/p&gt;

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

&lt;span class="nx"&gt;uploadButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currFiles&lt;/span&gt; &lt;span class="o"&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;files&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;After that, we get the current files in the object&lt;/p&gt;

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

&lt;span class="nx"&gt;uploadButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currFiles&lt;/span&gt; &lt;span class="o"&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;files&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;We then check to see if the currFiles array is not empty, get the first file in the array, and append that to our image element. We use the getElementById method to get the image element with an id of file-preview.&lt;/p&gt;

&lt;p&gt;After that, we add the image src to the src attribute of our image element and change the display of the image element from &lt;code&gt;display:none&lt;/code&gt; to &lt;code&gt;display:block&lt;/code&gt;. &lt;/p&gt;

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

&lt;span class="nx"&gt;uploadButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currFiles&lt;/span&gt; &lt;span class="o"&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;files&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currFiles&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currFiles&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;imagePreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;imagePreview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;
      &lt;span class="nx"&gt;imagePreview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Your final JS code should look like this:&lt;/p&gt;

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

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;uploadButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type="file"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;uploadButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currFiles&lt;/span&gt; &lt;span class="o"&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;files&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currFiles&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currFiles&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;imagePreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;imagePreview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;
      &lt;span class="nx"&gt;imagePreview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That is all for the code. The final output should look like this:&lt;/p&gt;

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

&lt;p&gt;It's a small image but it does the work of letting the user know that they have selected an image.&lt;/p&gt;

&lt;p&gt;Thanks for reading this.&lt;/p&gt;

&lt;p&gt;One interesting thing you could try to implement is zoom on click. When the user clicks on the preview image, they are able to see the image pop up like a modal and with more clarity.&lt;/p&gt;

&lt;p&gt;Recommended Resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file" rel="noopener noreferrer"&gt;MDN article on input type file&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL" rel="noopener noreferrer"&gt;MDN article on createObjectURL&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model" rel="noopener noreferrer"&gt;MDN article on the DOM&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Banner Image source: &lt;a href="https://web.dev/learn/forms/fields/" rel="noopener noreferrer"&gt;https://web.dev/learn/forms/fields/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>html</category>
    </item>
    <item>
      <title>Fixing Font issue with Parcel</title>
      <dc:creator>Kehinde Adeleke </dc:creator>
      <pubDate>Mon, 07 Feb 2022 01:44:06 +0000</pubDate>
      <link>https://dev.to/adeleke5140/fixing-font-issue-with-parcel-508o</link>
      <guid>https://dev.to/adeleke5140/fixing-font-issue-with-parcel-508o</guid>
      <description>&lt;p&gt;I just recently started using the parcel bundler for a project I was working on. I set up the dev and build commands, and set my path to &lt;code&gt;src/index.html&lt;/code&gt;. Unfortunately, all my fonts file in the &lt;code&gt;src/&lt;/code&gt; folder wouldn't show up in the compiled html file in the &lt;code&gt;dist&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  how I solved it
&lt;/h2&gt;

&lt;p&gt;I googled around a bit but there weren't that many issues as specific as mine. I read up on github and found out that, one way was to copy the fonts folder from the &lt;code&gt;src&lt;/code&gt; into the &lt;code&gt;dist&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;If you want to try this out, make sure the server isn't running by pressing &lt;code&gt;ctrl c&lt;/code&gt; in your terminal. After that, copy the fonts folder to the &lt;code&gt;dist&lt;/code&gt; folder and then run your build command again. In my case it was &lt;code&gt;npx parcel&lt;/code&gt; this is because I had specified my source to be &lt;code&gt;src/index.html&lt;/code&gt; in my package.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "source": "src/index.html",
  "scripts": {
    "dev": "parcel",
    "build": "parcel build"
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Voila! it worked quite alright.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>parcel</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
