<?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: gohashira</title>
    <description>The latest articles on DEV Community by gohashira (@gohashira).</description>
    <link>https://dev.to/gohashira</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%2F714377%2F82da1584-a9fe-480b-a583-13907104c9d0.jpeg</url>
      <title>DEV Community: gohashira</title>
      <link>https://dev.to/gohashira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gohashira"/>
    <language>en</language>
    <item>
      <title>I Tried Every Hot Programming Language</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Fri, 13 Dec 2024 05:11:24 +0000</pubDate>
      <link>https://dev.to/gohashira/i-tried-every-hot-programming-language-514f</link>
      <guid>https://dev.to/gohashira/i-tried-every-hot-programming-language-514f</guid>
      <description>&lt;p&gt;In this post, I'll make an attempt to compare GoLang, Zig, and Rust. And why Rust wins this comparison (for me).&lt;/p&gt;

&lt;h2&gt;
  
  
  Story Time!
&lt;/h2&gt;

&lt;p&gt;I wrote 3 of my projects in GoLang, Zig &amp;amp; Rust. These projects are sufficiently big to get a good idea about the language fundamentals, shortcomings, and whether there's a problem with the language, the framework, or the ecosystem.&lt;/p&gt;

&lt;p&gt;TIP: feel free to jump to TLDR section to just get the damn answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  GoLang
&lt;/h3&gt;

&lt;p&gt;I started building developer tools a few months back, initially with GoLang.&lt;/p&gt;

&lt;p&gt;The first one was a basic database management &amp;amp; migrations utility (&lt;a href="https://github.com/fossMeDaddy/dbdaddy" rel="noopener noreferrer"&gt;dbdaddy&lt;/a&gt;) and I genuinely had fun working with GoLang.&lt;/p&gt;

&lt;p&gt;Even though this was my very first attempt with GoLang building something more serious than Advent Of Code &amp;amp; 1 billion row challenge problems, &lt;strong&gt;I was surprised that it took me less than a week to get proficient at it&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zig
&lt;/h3&gt;

&lt;p&gt;All this while, I was dabbling with Zig on the side (nothing too serious). I heard about Redis changing their license to a "technically non-open-source" license.&lt;/p&gt;

&lt;p&gt;And I thought to myself: &lt;em&gt;how hard can it be to build a new open-source redis in zig?&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Fast-Forward 2 months later: &lt;em&gt;damn.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The basic idea behind "&lt;a href="https://github.com/fossMeDaddy/gbcache" rel="noopener noreferrer"&gt;GbCache&lt;/a&gt;" was an LRU-based in-memory cache but the actual source of truth was to be saved on disk along with features like notifications for specific key/value changes caused and obviously TTLs assigned to keys.&lt;/p&gt;

&lt;p&gt;It is impressive how explicit Zig is, which makes it all the more simple and easier to work with.&lt;/p&gt;

&lt;p&gt;I started GbCache from the perspective of "if it were to go HyperScale™ tomorrow, can it handle the load?"&lt;/p&gt;

&lt;p&gt;This perspective drove me to rule out GoLang because if I am unable to reason with extreme certainty about the memory allocations, I won't have complete control over the speed.&lt;/p&gt;

&lt;p&gt;Doing things from this perspective is a really great learning experience because suddenly you start seeing all the points in your program that might blow up, run out of memory or may become a bottleneck —&lt;em&gt;the hot paths in your code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Due to Zig's explicitness, I was sure of exactly where &amp;amp; when I am allocating memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But... Zig is NOT a memory-safe language at the end of the day and I am a guy with skill issues the size of Everest.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;enters rust&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the last 2 years, I've tried and rage-quit on Rust 3 times. Coming from a JavaScript background where we have a bajillion gb ram in our macbook m69 maxes, I never &lt;em&gt;really&lt;/em&gt; understood why Rust had those rules, and going in with the hype was probably a bad angle to look at it from.&lt;/p&gt;

&lt;p&gt;Even though I rage-quit several times, Rust was still in the back of my mind, its weird syntax, frustrating memory rules, and mind-boggling lifetimes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But something hit me while writing Zig... &lt;em&gt;I already was keeping track of all these memory rules and lifetimes but as a mental overhead&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started noticing patterns and boilerplate in my Zig code trying to do what Rust already does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rust
&lt;/h3&gt;

&lt;p&gt;While building the CLI client for &lt;a href="https://github.com/fossMeDaddy/sfs-cli" rel="noopener noreferrer"&gt;SFS&lt;/a&gt; (SFW name - "Simple File Storage") I decided to give Rust another try.&lt;/p&gt;

&lt;p&gt;This time around while going through the rust book, I started to feel the "why" of it all.&lt;/p&gt;

&lt;p&gt;The most fundamental thing that I love about Rust is the ownership &amp;amp; borrowing-based &lt;em&gt;mental model&lt;/em&gt; of memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even though this model of owned &amp;amp; referenced memory is imaginary, it is a convenient mental model to reason about and incurs less overhead over my head&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As opposed to the classic mental memory model that languages like C &amp;amp; Zig incur on your head. &lt;em&gt;Have to track individual memory allocations &amp;amp; their lifetimes in my head? no thanks!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;h4&gt;
  
  
  GoLang
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;FAST &lt;em&gt;(like your 5 MAUs are gonna need it lmao)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;reliable&lt;/li&gt;
&lt;li&gt;stupid simple, language is never standing between you &amp;amp; your goal&lt;/li&gt;
&lt;li&gt;great ecosystem of packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Zig
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;BLAZING FAST&lt;/li&gt;
&lt;li&gt;stupid simple&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Rust
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;BLAZING FAST&lt;/li&gt;
&lt;li&gt;reliable&lt;/li&gt;
&lt;li&gt;great ecosystem of packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  All Of Them
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;amazing error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're an everyday normal mo— backend engineer and like doing numbers on their sprint performance, your best choice is probably &lt;strong&gt;GoLang&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"but my company doesn't use GoLa—"&lt;br&gt;
"leave the company, leave it, use the right job for the tool. leave the company."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To me, GoLang is like an arranged marriage where you never &lt;em&gt;feel that rush&lt;/em&gt; in your heart but it never lets you down, it's your ride-or-die companion and you can bet your whole life on it.&lt;/p&gt;

&lt;p&gt;But my friend if you are &lt;em&gt;looking&lt;/em&gt; for that rush keep reading on!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Puran
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;bu— but i want that rush... i want to feel my heart explode on catching a mere glance at their ey-syntax... i want to feel like i am in heaven when I'm with them and in hell when I'm not...&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Let's have a quick look at an example of multi-threaded safety in Rust.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 32-bit integer allocated on the heap&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// trying to edit the value&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;handles&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// WAITING FOR ALL THE THREADS TO COMPLETE&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a heap-allocated value and there are 10 threads trying to modify it independently.&lt;/p&gt;

&lt;p&gt;This code is unsafely accessing the &lt;code&gt;counter&lt;/code&gt; variable as all the threads will try to modify &lt;code&gt;counter&lt;/code&gt; simultaneously.&lt;/p&gt;

&lt;p&gt;In other languages, similar code will happily compile and run.&lt;/p&gt;

&lt;p&gt;If you have worked in a multithreaded environment before, your first thought might be to use a "mutex" to prevent race conditions in updating the &lt;code&gt;counter&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;But it's easy to miss little things like this in a big codebase due to human error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rust won't even let this program compile.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Due to ownership &amp;amp; borrowing rules, the compiler will detect that you are mutably borrowing &lt;code&gt;counter&lt;/code&gt; in the first thread in the first iteration of the for loop... &lt;em&gt;ok until now&lt;/em&gt;... the second iteration also wants to mutably borrow &lt;code&gt;counter&lt;/code&gt; parallelly? &lt;em&gt;unsafe! raise a &lt;strong&gt;COMPILE-TIME ERROR&lt;/strong&gt;!!&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;referencing or "borrowing" a value from its owner with the intention of mutating/modifying is called a "mutable borrow"&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main.rs|8 col 36-38 error| cannot borrow `*counter` as mutable more than once at a time `*counter` was mutably borrowed here in the previous iteration of the loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In situations like these, other languages don't give you any error at all. It's your responsibility to inspect the correctness, Rust prevents that.&lt;/p&gt;

&lt;p&gt;Constructs like these spread across the language help you to not shoot yourself in the foot (often).&lt;/p&gt;

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

&lt;p&gt;IT DEPENDS!&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;really&lt;/em&gt; wish there were a language that was &lt;em&gt;the answer&lt;/em&gt; and even if GoLang comes pretty close to that, it really depends on your use case and most importantly, your team.&lt;/p&gt;

&lt;p&gt;for me, Rust is a pleasure to work with (for now, who knows... hehe)&lt;/p&gt;

&lt;p&gt;folks at &lt;a href="https://docs.tigerbeetle.com" rel="noopener noreferrer"&gt;TigerBeetle&lt;/a&gt; took a chance on &lt;strong&gt;Zig&lt;/strong&gt; and they're happy with it.&lt;/p&gt;

&lt;p&gt;Primeagen is happier with &lt;strong&gt;Zig&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;for Jarred Sumner, &lt;strong&gt;Zig&lt;/strong&gt; is fine, he wrote &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; in &lt;strong&gt;Zig&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mitchell Hashimoto (guy behind HashiCorp) is writing &lt;a href="https://mitchellh.com/writing/ghostty-is-coming" rel="noopener noreferrer"&gt;ghostty&lt;/a&gt; in &lt;strong&gt;Zig&lt;/strong&gt;, a BLAZING FAST termin—&lt;/p&gt;

&lt;p&gt;.&lt;br&gt;
.&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;wait...&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>rust</category>
      <category>go</category>
      <category>learning</category>
    </item>
    <item>
      <title>How I Got a Job as a Self-Taught Developer without a College Degree</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Sat, 27 Jan 2024 12:39:18 +0000</pubDate>
      <link>https://dev.to/gohashira/how-i-got-a-job-as-a-self-taught-developer-without-a-college-degree-3dll</link>
      <guid>https://dev.to/gohashira/how-i-got-a-job-as-a-self-taught-developer-without-a-college-degree-3dll</guid>
      <description>&lt;p&gt;I am a 20yo self-taught engineer who recently retired from frontend dev (cuz' I got sick of it) and I've been working with web tech almost every day for the past 4 years.&lt;/p&gt;

&lt;p&gt;3 years of which, I spent writing production code&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;so much garbage code was pushed in these years, god I wonder what an idiot my employer was.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I love solving problems (also the reason why I left frontend) and you can find me working on &lt;a href="https://github.com/fossMeDaddy" rel="noopener noreferrer"&gt;FOSSMeDaddy!&lt;/a&gt; or playing chess in my free time. (I don't have a social life, duh...)&lt;/p&gt;

&lt;p&gt;In this post, I'm gonna use the word "I" a lot of times to indicate that these were my experiences and of course, I'm gonna be highly biased towards them, you aren't supposed to hear "you should" instead of "I" :)&lt;/p&gt;

&lt;p&gt;I hope you enjoy reading this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Gig
&lt;/h2&gt;

&lt;p&gt;The spark ignited in '20 when I first watched Clever Programmer's Netflix Clone video in React.js.&lt;/p&gt;

&lt;p&gt;He made it seem simple and I was so excited, I jumped head-first only knowing how to declare variables in JavaScript and some basic Python knowledge from high school.&lt;/p&gt;

&lt;p&gt;Now, I know those guys aren't the best place to learn from these days mainly due to the heavy pushing of their expensive boot camp courses, but their YT tutorials really helped me at that time, and you know what they say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;you never forget your first. (mentor)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No joke, I akshually started my web dev journey by writing a &lt;code&gt;useState&lt;/code&gt; not knowing what the hell it, or anything I was seeing, was.&lt;/p&gt;

&lt;p&gt;I made 2 purely frontend clones while strictly following the tutorials. With every line I wrote, I learned a bit of both React and JavaScript, classifying which is React and which is JS.&lt;/p&gt;

&lt;p&gt;After 2 projects, I lost my patience, closed YT, and continued with the 3rd one - Instagram Clone.&lt;/p&gt;

&lt;p&gt;It felt like a freakin' battlefield... errors everywhere, the backend console, the frontend console, my life, CSS console, everywhere! but I made it through all those errors, googling my way through.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;kids... ChatGPT didn't exist at that time, we used to do everything from StackOverflow and Logrocket Blogs&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fast-forward 3 months of more random projects, I started applying for internships on Internshala (the best platform to apply for internships, In India at least).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📝&lt;/p&gt;

&lt;p&gt;The key is to get in the door somehow, Once you are in the industry, it's relatively easy to get new and slightly better opportunities while your resume fills up with experience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I specifically applied for unpaid internships in startups. That way, it was easier for me to get in, there was no pressure to manage skill-related expectations and it was implicitly clear in everyone's mind at the company that this person was here to learn and would make tons of mistakes.&lt;/p&gt;

&lt;p&gt;After getting in, All I had to do now was learn and shoot down prod less (ik... impossible right?!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn, Learn, Learn
&lt;/h2&gt;

&lt;p&gt;I never went to any Bootcamp or ever took a udemy course on the things I did but I can for sure tell now, I was better off not taking them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📝&lt;/p&gt;

&lt;p&gt;Yes, these bootcamps and zero-to-hero courses give you the knowledge but also give you a weird fear of leaving them, you get too comfortable in the course and forget that they are highly spoon-fed environments to make you learn things easily.&lt;/p&gt;

&lt;p&gt;This situation is also known as &lt;em&gt;The Tutorial Hell&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lucky for me, I unknowingly avoided it.&lt;/p&gt;

&lt;p&gt;Being more hands-on and spending more Time In The Saddle, I learned stuff better, reading the docs for the APIs &amp;amp; libraries I was using gave me clarity on how things work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca5eepgl3ilyhnxktq0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca5eepgl3ilyhnxktq0s.png" alt="more TimeInTheSaddle are the best" width="597" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The internship was a transformative experience in terms of my knowledge. It was the first time when I grasped basic concepts like APIs, Frontend-Backend connectivity, Authentication &amp;amp; Security, the Importance of efficiency, Code readability, and Communication in a professional environment.&lt;/p&gt;

&lt;p&gt;I burned out after completing the 9-month internship, but after a week's break, I was back doing projects and applying to more opportunities.&lt;/p&gt;

&lt;p&gt;If I was doing it just for the money's sake, with no passion, I would've never taken the unpaid internship in the first place and would've sloshed around the shallow waters doing 6-month bootcamps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📝&lt;/p&gt;

&lt;p&gt;You can become a good developer if you do it for the money but at some point, you just have to be passionate &amp;amp; curious about what you do,&lt;/p&gt;

&lt;p&gt;That's what separates a good developer from a great developer.&lt;/p&gt;

&lt;p&gt;-ThePrimeagen&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;i know i've quoted him twice... i like primeagen okay! he makes me want to be a better ma- develop- engineer!&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;There are now, no more takeaways left in this post.&lt;/p&gt;

&lt;p&gt;But before you navigate away, I wanna talk about some of the pros &amp;amp; cons of ditching college.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;More of a personal choice than a logical one.&lt;/p&gt;

&lt;p&gt;I hated every living minute at school, well, apart from the social interactions, you know friends &amp;amp; stuff...&lt;/p&gt;

&lt;p&gt;And I didn't wanna continue that life into college, I love studying Physics, I love studying CS &amp;amp; I love studying Math, but I never loved studying them just to clear an exam, everything is exam-oriented and I am definitely not the type of guy who likes being told by teachers "we can't study that, that's not in the syllabus"&lt;/p&gt;

&lt;p&gt;So I struck out on my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros
&lt;/h2&gt;

&lt;p&gt;Whenever I tell recruiters that I didn't go to college to pursue being a developer on my own, I usually get a positive, mildly impressed reaction from their faces. From there the conversation is only about skills.&lt;/p&gt;

&lt;p&gt;It honestly does the filtering of bad companies for me, I don't wanna be in companies that value degrees above actual skill sets and I like being around people who were hired this way, who love what they do just as much or more than I do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Zero social life.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No proper learning curriculum &amp;amp; structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing out on the fundamental &amp;amp; low-level knowledge taught in colleges.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing out on opportunities that a good college fetches for you without you having to search for everything.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recruiters doubt your ability to persevere in the job.&lt;br&gt;&lt;br&gt;
Just the fact that you went to college for several years, did what you were told to do, and achieved relatively above-average grades shows your discipline &amp;amp; ability to persevere.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These gaps can be filled to an extent but you really can't do about the numerous opportunities you miss out on that are CS University exclusive.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did parents say?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x8ck6h3axizmrgdi29p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x8ck6h3axizmrgdi29p.png" alt="3 idiots father won't agree meme" width="640" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made a bargain.&lt;/p&gt;

&lt;p&gt;after passing out from school, I had one year. if I can prove someone will hire me and I can sustain myself, they'll let me do whatever I want or else... college.&lt;/p&gt;

&lt;p&gt;and guess what?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Neural Nets for Web Developers #1: Quick Start w/ TensorFlow</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Tue, 16 Jan 2024 15:51:45 +0000</pubDate>
      <link>https://dev.to/gohashira/neural-nets-for-web-developers-1-quick-start-w-tensorflow-4lel</link>
      <guid>https://dev.to/gohashira/neural-nets-for-web-developers-1-quick-start-w-tensorflow-4lel</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this multiple-part series of posts, I plan to introduce the concepts of Deep Learning to my fellow web developers.&lt;/p&gt;

&lt;p&gt;In this post, we'll start from the very first question that arises after hearing the word Neural Nets "&lt;em&gt;What is a Neural Net?&lt;/em&gt;" and gradually work our way up to our first Deep Learning Model making predictions on our data.&lt;/p&gt;

&lt;p&gt;In the last few posts of this series, I've planned to include a project laying out and implementing advanced DL topics like Convolutional Neural Nets &amp;amp; more.&lt;/p&gt;

&lt;p&gt;Without further ado, let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Neural Net?
&lt;/h2&gt;

&lt;p&gt;Let's start with an analogy &amp;amp; then get to the first principles.&lt;/p&gt;

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

&lt;p&gt;This is a figure depicting the structure of a single Biological Neuron.&lt;/p&gt;

&lt;p&gt;There are billions of these in your brain &amp;amp; your body connected to each other at terminals and communicate via certain chemicals (neurotransmitters) and electricity signals.&lt;/p&gt;

&lt;p&gt;The junction between 2 neurons is called a synapse where electric signals from neurons get converted into these chemicals, which then travel the gap in the synapse &amp;amp; get converted into electric signals again in the second neuron.&lt;/p&gt;

&lt;p&gt;When your brain and/or body is doing an activity, that to some extent, has repetitive patterns in it, certain networks consisting of these neurons get activated periodically again &amp;amp; again.&lt;/p&gt;

&lt;p&gt;Mind-blowingly enough (pun intended), after a few repetitions, these networks begin adapting certain parts of the neurons in them to facilitate faster &amp;amp; stronger electric signal transfer.&lt;/p&gt;

&lt;p&gt;This happens when you learn to do something physically or mentally.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here, when I say networks being "activated"&lt;br&gt;&lt;br&gt;
I mean, the neurons in the network serially fire electrochemical signals causing some of the subsequent neurons to fire &amp;amp; some to not fire resulting in a unique pattern of firing of signals with different intensities,&lt;/p&gt;

&lt;p&gt;In turn, this causes other connected networks to activate that MIGHT be connected to other areas of your body or even your brain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Understanding "learning" in terms of connections
&lt;/h3&gt;

&lt;p&gt;In our brains, every thought, activity or response corresponds to a certain network of neurons being activated.&lt;/p&gt;

&lt;p&gt;While reading this post you can 3asily 1denti5y 3ords eve9 if they are not exactly what you see.&lt;/p&gt;

&lt;p&gt;In your lifetime, reading millions of words has developed strongly connected neural networks in your brain taking input from eyes &amp;amp; outputting "ideas" for what the next whole word could be.&lt;/p&gt;

&lt;p&gt;The same happens when you speak, activating certain neural networks that rigorously take input from your mouth muscles moving &amp;amp; depict the next relevant movement such that you can produce the next relevant word the instant it "pops up" in your head.&lt;/p&gt;

&lt;p&gt;It was a long run of saying non-sensical words to meaningful conversations.&lt;/p&gt;

&lt;p&gt;The tireless effort from moving your legs randomly to walking with outstanding balance.&lt;/p&gt;

&lt;p&gt;bicycling, learning javascript, learning math.&lt;/p&gt;

&lt;p&gt;All of it boils down to certain groups of neurons firing in certain patterns millions of times to produce the "conscious you".&lt;/p&gt;

&lt;p&gt;Have you noticed a pattern till now?&lt;/p&gt;

&lt;p&gt;All of the learnable mental/physical actions you did, at first, started with randomness and slowly got more accurate or "improved".&lt;/p&gt;

&lt;p&gt;Let's define "improvement" on an abstract basis:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;start with randomness&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;calculate accuracy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change in whatever direction that helps improve accuracy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;repeat until the maximum possible accuracy is achieved&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Artificial Neural Networks merely mimic this process and in the past few decades, we've started to reap the benefits.&lt;/p&gt;

&lt;p&gt;This abstract process of improvement is even followed by nature itself in a modified approach, outlined by Darwin's theory of evolution (Survival of the fittest).&lt;/p&gt;

&lt;p&gt;Let's look into ways of how can we replicate this process digitally.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Perceptron
&lt;/h2&gt;

&lt;p&gt;After many iterations of ON/OFF neurons mimicking biological neurons, in 1943, &lt;em&gt;Warren McCulloch&lt;/em&gt; and &lt;em&gt;Walter Pitts&lt;/em&gt; proposed the "Perceptron" model which was more well-suited to computers than other models depending on the binary form of signals.&lt;/p&gt;

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

&lt;p&gt;Let's break this figure down into components.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Think of the AN (artificial neuron) as a machine or a &lt;em&gt;big mathematical function that receives some input, processes it and generates an output&lt;/em&gt; where the output depends on the input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;X1&lt;/code&gt;, &lt;code&gt;X2&lt;/code&gt; &amp;amp; &lt;code&gt;X3&lt;/code&gt; here, are the numerical inputs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The inputs go into the summation unit that does a &lt;em&gt;weighted sum&lt;/em&gt; of all the inputs or &lt;code&gt;X&lt;/code&gt;'s (more on "weighted sum" in the next few sections)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick Note:&lt;br&gt;&lt;br&gt;
The greek letter "Σ" is called "sigma" and in Math we use it to signify where addition of multiple values is being done.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The summation unit then passes the summed-up result into a literal Mathematical function, this function could be anything that suits best, exponential, linear, sinusoidal, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Okay... so this appears like a really big "machine" so to speak, but where's the "learning part"?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The "learning part" lies in the "weighted sum" in the summation component of the AN, let's look into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summation Unit and Weighted Sum
&lt;/h3&gt;

&lt;p&gt;The summation unit of the neuron receives input(s) in an array like so:&lt;br&gt;&lt;br&gt;
&lt;code&gt;[12.495, 200.001, 89.055, 79.402, 203.379, ...]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Or more generalized as:&lt;br&gt;&lt;br&gt;
&lt;code&gt;[x1, x2, x3, x4, ... xn]&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The whole array is first multiplied by another array of the same length containing the "weights":&lt;br&gt;&lt;br&gt;
&lt;code&gt;[x1, x2, ... xn]&lt;/code&gt; * &lt;code&gt;[w1, w2 ... wn]&lt;/code&gt; = &lt;code&gt;[w1 * x1, w2 * x2, ... wn * xn]&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;More you know:&lt;br&gt;&lt;br&gt;
This is also known as a "Vector Product" of 2 lists/matrices&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And then all the elements of the resultant "weighted" array are summed up to produce one number (also known as the weighted sum).&lt;/p&gt;

&lt;p&gt;Along with that we also add &lt;em&gt;one more number&lt;/em&gt; to the final weighted sum number, called a "bias". (more on this number in the next section)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The resultant number is passed off to the last component of our AN, the literal mathematical function&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A number to multiply with is often called a weight as the product is more/less "weighted" than the original number, for example:&lt;br&gt;&lt;br&gt;
12 * 1.2 = 14.4&lt;br&gt;&lt;br&gt;
In this simple operation, 1.2 was the weight which was weighted to 12 to produce a weighted product 14.4.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But you recently mentioned that an AN is like a machine, a mathematical function whose output only depends on the inputs given?&lt;/p&gt;

&lt;p&gt;What are these w1, w2, w3...?&lt;br&gt;&lt;br&gt;
They don't seem to be dependent on anything? what are their values?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You got me there!&lt;/p&gt;

&lt;p&gt;The weights array is initially &lt;em&gt;randomized&lt;/em&gt; &amp;amp; contains random numbers.&lt;/p&gt;

&lt;p&gt;And I know that this will produce a totally random output after going through the literal mathematical function.&lt;/p&gt;

&lt;p&gt;But that's part of the plan!&lt;/p&gt;

&lt;p&gt;Recall our definition of improvement, &lt;strong&gt;the first step is to start randomly&lt;/strong&gt; AND THEN, steer towards maximum accuracy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9g4i8vygssuaec6huvx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9g4i8vygssuaec6huvx3.png" alt="training a machine learning system meme" width="703" height="827"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Machine Learning with A Hypothetical Perceptron
&lt;/h2&gt;

&lt;p&gt;Let's try to understand the whole process with a simple, highly overused example of housing prices.&lt;/p&gt;

&lt;p&gt;Let's look at this example of data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3765&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7530&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11295&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18825&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22590&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26355&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33885&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;37650&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;41415&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;48945&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;52710&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;56475&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;house_prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16203815&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11924806&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15363025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20681588&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23343728&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31297816&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45029324&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;48653516&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;43981690&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;52140160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64208930&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;59116732&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;69043050&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;66664916&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;77795170&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, our goal is to look at this data &amp;amp; predict for an unseen given house area, what should be the price of the house.&lt;/p&gt;

&lt;p&gt;Our hypothetical perceptron for this problem looks something like this:&lt;/p&gt;

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

&lt;p&gt;Let's start with defining a mathematical function for the last component of the Perceptron,&lt;/p&gt;

&lt;p&gt;Because we aren't doing something crazy here, let's set the function to the identity function in Math which just outputs the exact same input that is passed in it.&lt;/p&gt;

&lt;p&gt;Let's now go through the process of "training" this Perceptron (hypothetically):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;we pass in our first house's area in as an array containing one number like this: &lt;code&gt;[A1]&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the summation unit takes its weighted sum with &lt;code&gt;[w1]&lt;/code&gt; weights and adds the "bias" number &lt;code&gt;b&lt;/code&gt; to the resultant.&lt;/p&gt;

&lt;p&gt;The bias terms and weight(s) are randomized initially,&lt;/p&gt;

&lt;p&gt;Resultant number = &lt;code&gt;(A1 * w1) + b&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This resultant number is then passed into our identity function.&lt;/p&gt;

&lt;p&gt;If we had more than 1 input other than the house area &lt;code&gt;A&lt;/code&gt; let's say no. of bedrooms, then the weighted sum + bias would've looked like this:&lt;br&gt;&lt;br&gt;
(&lt;code&gt;A1 * w1 + B1 * w2) + b&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;identity function receives &lt;code&gt;(A1 * w1) + b&lt;/code&gt; and spits out &lt;code&gt;(A1 * w1) + b&lt;/code&gt; i.e. same as the input&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we compare the numeric difference between &lt;code&gt;(A1 * w1) + b&lt;/code&gt; and the actual price of the house for the area &lt;code&gt;A1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we change the values of &lt;code&gt;w1&lt;/code&gt; &amp;amp; &lt;code&gt;b&lt;/code&gt; by some amount and repeat the above steps for &lt;code&gt;A2&lt;/code&gt;, &lt;code&gt;A3&lt;/code&gt; &amp;amp; so on...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we keep on doing this until our predicted values are close to actual values throughout the data and we've TUNED the weights &amp;amp; bias(es)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Machine Learning with an Actual Perceptron in TensorFlow
&lt;/h2&gt;

&lt;p&gt;We've seen in an overview how perceptrons work, let's implement them using TensorFlow now.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog is available as a &lt;a href="https://colab.research.google.com/drive/1av38qcWEDi2M6FUjlaa0iRvYMj-eUTWo?usp=sharing" rel="noopener noreferrer"&gt;Google Colab notebook&lt;/a&gt; where you can easily run all the code from the comfort of your web browser,&lt;/p&gt;

&lt;p&gt;No need to jump through a dozen hoops to get your Python environment up &amp;amp; running.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt; &lt;span class="c1"&gt;# 0
&lt;/span&gt;
&lt;span class="n"&gt;ml_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="c1"&gt;# 1
&lt;/span&gt;    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;# 2
&lt;/span&gt;    &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mae&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optimizers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SGD&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# 3
&lt;/span&gt;
&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 4
&lt;/span&gt;
&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="c1"&gt;# 5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down into pieces to understand more clearly what's happening behind the scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keras Sequential API (# 1)
&lt;/h3&gt;

&lt;p&gt;Keras module in Tensorflow helps us work with deep neural networks.&lt;/p&gt;

&lt;p&gt;Let's understand with examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code corresponds to the below neural network structure behind the scenes:&lt;/p&gt;

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

&lt;p&gt;If you look at this figure closely, you'll find that the ANs are connected to each other in a special way where each AN in a layer receives multiple inputs &amp;amp; generates 1 output but sends the output to ALL of the neurons in the next layer.&lt;/p&gt;

&lt;p&gt;ANs in a layer aren't connected to themselves but are connected to all of the ANs in the previous and subsequent layers.&lt;/p&gt;

&lt;p&gt;This type of layering &amp;amp; connecting architecture is called "Dense" architecture and is one of the most commonly used in Deep learning models.&lt;/p&gt;

&lt;p&gt;The dense architecture helps us to put as many ANs &amp;amp; layers of ANs as we want and the model would learn its weights &amp;amp; biases accordingly.&lt;/p&gt;

&lt;p&gt;Let's use our imagination aided by this figure to hypothetically train this example ANN (Artificial Neural Network):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The array of inputs containing numbers is fed into our first layer containing 3 Neurons where each neuron receives all the inputs in an array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each neuron in the first layer (layer #1) then processes the input array independently, putting the inputs through the summation unit to compute a weighted sum &amp;amp; a bias and then the activation function to compute the final output.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TensorFlow calls the mathematical function in the neuron an "activation function" We'll respect the same convention from now on&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final output from each neuron in the current layer is then sent to all of the neurons in the subsequent layer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The subsequent layer or layer #2 neurons receive the outputs of ALL the neurons in the previous layer, compute the weighted sum with bias &amp;amp; run the activation function on the resultant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The output layer which is nothing but a simple array, collects the output of each layer #2 neuron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[Explanation Point]&lt;br&gt;&lt;br&gt;
Here, just for the sake of continuing this process, we'll assume that there's a dataset that has 3 numerical values for its &lt;em&gt;features&lt;/em&gt; and 5 numerical values for its &lt;em&gt;labels&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Independent values are called "features" in Machine Learning&lt;br&gt;&lt;br&gt;
for example: house area, no. of bedrooms, etc.&lt;/p&gt;

&lt;p&gt;Dependent values are called "labels" in Machine Learning&lt;br&gt;&lt;br&gt;
for example: house price, etc.&lt;/p&gt;

&lt;p&gt;Labels are dependent on Features that's why we try to find patterns in features relating to the labels.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We'll compare the difference in the 5 predicted/output label values with the actual label values in our hypothetical dataset corresponding to the feature values we predicted upon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update each weight &amp;amp; bias, do a comparison again and feed in the next 3 values in the neural network and so on until we have JUST RIGHT values of weights &amp;amp; biases.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In &lt;code&gt;tf.keras.layers.Dense(1)&lt;/code&gt; we tell TensorFlow to scaffold a new layer with 1 neuron where every neuron in the layer has the default, identity function (aka linear function) set as their activation function.&lt;/p&gt;

&lt;p&gt;So this means, the weighted sum of their inputs + bias is each neuron's actual output.&lt;/p&gt;

&lt;p&gt;To change the activation function for the neurons of a particular layer, we can do:&lt;br&gt;&lt;br&gt;
&lt;code&gt;tf.keras.layers.Dense(n_neurons, activation="...")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are some predefined activation functions like the default "linear", or "elu", "relu", "sigmoid", etc. that help train ANNs better by modulating the outputs of the neurons for a particular layer.&lt;/p&gt;

&lt;p&gt;Now, allow me to visualize the importance of bias numbers for you.&lt;/p&gt;

&lt;p&gt;There might be a neuron itself in the network whose output doesn't strongly depend on the overall output of the network. By providing a changeable bias number added to the weighted sum for the neuron in the system, we can "dim" or "highlight" the influence of that neuron.&lt;/p&gt;

&lt;p&gt;Coming to our original code, we can see that we've defined an ANN that has only 1 layer of neuron(s) and that layer contains only 1 neuron.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ml_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="c1"&gt;# 1
&lt;/span&gt;    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now that we know how to code up an ANN &amp;amp; how Sequential API works, let's code up the next step of the process - calculating loss &amp;amp; optimizing the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Losses &amp;amp; Optimizers (# 2)
&lt;/h3&gt;

&lt;p&gt;After we've scaffolded our Neural Net, we need to compile it with a loss function &amp;amp; an optimizer algorithm, let's understand what they are here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;# 2
&lt;/span&gt;    &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mae&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optimizers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SGD&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 generally use 2 types of loss-calculating functions - MAE &amp;amp; MSE&lt;/p&gt;

&lt;p&gt;Mean Absolute Error (MAE) is calculated by taking the difference between each predicted label and the actual data label.&lt;/p&gt;

&lt;p&gt;For example, let's say we have 3 predicted labels &amp;amp; corresponding 3 actual data labels - &lt;code&gt;[p1, p2, p3]&lt;/code&gt; &amp;amp; &lt;code&gt;[y1, y2, y3]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Then the difference will be - &lt;code&gt;[abs(p1 - y1), abs(p2 - y2), abs(p3 - y3)]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;abs()&lt;/code&gt; the function calculates the absolute value of the difference (disregards any -ve sign)&lt;/p&gt;

&lt;p&gt;And then, takes the average of the difference array.&lt;/p&gt;

&lt;p&gt;This gives out the MAE loss for that particular prediction.&lt;/p&gt;

&lt;p&gt;Mean Squared Error (MSE) is similar in the sense that it only takes the square of the corresponding differences instead of taking the absolute value.&lt;/p&gt;

&lt;p&gt;Therefore, MSE too acts as an important loss function if you want to penalize the model more for more significant differences.&lt;/p&gt;

&lt;p&gt;In this case, we use MAE loss by specifying a string &lt;code&gt;"mae"&lt;/code&gt; as the loss function parameter and TensorFlow will take care of the rest.&lt;/p&gt;

&lt;p&gt;Coming to the topic of optimizers, for now, just know that optimizers like Stochastic Gradient Descent (SGD) or Adam take in the loss value from the loss function, and set the factor by which the weights &amp;amp; biases are changed.&lt;/p&gt;

&lt;p&gt;At each iteration of the data, TensorFlow does all of this for us.&lt;/p&gt;
&lt;h3&gt;
  
  
  Building The Model
&lt;/h3&gt;

&lt;p&gt;So until now, our model actually looks something like this:&lt;/p&gt;

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

&lt;p&gt;We've been assuming that there will only be one input feature to train on but the model doesn't know this yet.&lt;/p&gt;

&lt;p&gt;According to the TF model, The number of inputs could be anywhere ranging from 1 to infinity, which also means that the weights to be assigned to each input feature could be anywhere ranging from 1 to infinity.&lt;/p&gt;

&lt;p&gt;To specify the input shape of the data, we call the &lt;code&gt;.build()&lt;/code&gt; function of the TF model that takes in a tuple as its first argument to define the shape of the input data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tuple argument &lt;code&gt;(None, 1)&lt;/code&gt; signifies the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;None&lt;/code&gt; - any number of rows of the data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;1&lt;/code&gt; - 1 number of features per row of the data&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that our features have to be passed in as a row-column array with 1 as the length of the column like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;house_areas&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="mf"&gt;3765.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7530.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;11295.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;15060.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;18825.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;22590.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;26355.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;30120.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;33885.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;37650.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;41415.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;45180.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;48945.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;52710.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;56475.&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 shape of our data is &lt;code&gt;(15, 1)&lt;/code&gt; (15 rows &amp;amp; 1 columns).&lt;/p&gt;

&lt;p&gt;Now our model knows how many features will be passed in it in one go i.e. 1.&lt;/p&gt;

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

&lt;p&gt;Calling &lt;code&gt;.build()&lt;/code&gt; always before training the model isn't necessary at all as TF automatically sets the input shape once we start training with the data,&lt;/p&gt;

&lt;p&gt;For the sake of showing the model summary which requires input shape to show the correct number of parameters, I've explicitly called the &lt;code&gt;.build()&lt;/code&gt; function.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;The convenient function &lt;code&gt;.summary()&lt;/code&gt; provides us with a summary of our TF model, let's have a look at what it has to say about our model:&lt;/p&gt;

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

&lt;p&gt;In a descriptive manner, the function &lt;code&gt;.summary()&lt;/code&gt; listed out the layers along with their type, output data shape &amp;amp; parameters (number of weights &amp;amp; biases)&lt;/p&gt;

&lt;p&gt;In our case, this is exactly what we expected, 1 tunable/trainable weight number and 1 tunable/trainable bias number which in total is 2 trainable parameters.&lt;/p&gt;

&lt;p&gt;And here's the icing on the cake when we return all of the trainable params using &lt;code&gt;ml_model.weights&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gp87oh36p4o5k018jjl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gp87oh36p4o5k018jjl.png" alt="trainable params of the tensorflow model" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first element in the array lists all the weights per input and the second element lists all the biases per neuron.&lt;/p&gt;

&lt;p&gt;Exactly 2 trainable variables where apparently weights are initialized to random values &amp;amp; biases are initialized to 0.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing the Data
&lt;/h3&gt;

&lt;p&gt;This step generally comes at the tippy top of the process but for the sake of learning &amp;amp; and the format of this post, Let's visualize our data a little here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;house_prices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;House area (sq. ft)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;House pricing USD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;blockquote&gt;
&lt;p&gt;Please excuse the accuracy here, given how little time I spent generating it, I like how it scales :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Again, as visualizing comes at the top of the ML process, it'll be the right time to point out that this data's features scale/increase linearly as the prices increase.&lt;/p&gt;

&lt;p&gt;This means that if we can figure out the equation of a straight line where we assume that all the data points lie on it such that our assumption of the line's equation variable results in the minimum difference of the actual points from line points for a particular point, then our job would be done &amp;amp; our model would perform good enough.&lt;/p&gt;

&lt;p&gt;Let's do just that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Training the Model
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ml_model_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;house_prices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;To train our TF model, we call the model's &lt;code&gt;.fit()&lt;/code&gt; function giving in the features array as the first argument &amp;amp; labels array as the second argument, passing an optional parameter called &lt;code&gt;epochs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In our case, our model will go through the whole feature sample 100 times (i.e. number of epochs) with the set weights &amp;amp; biases, calculate &amp;amp; optimize loss after every epoch and repeat 100 times.&lt;/p&gt;

&lt;p&gt;While printing loss at each epoch, TensorFlow also stores the loss at each epoch during training time and can be accessed from the returned object's &lt;code&gt;.history["loss"]&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Let's plot our epoch vs. loss curve using Matplotlib (a popular graphing library)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ml_model_history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No. of epochs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;em&gt;There's nothing more satisfying than seeing your model's loss decreasing at every epoch!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here, the loss acutely decreases as TensorFlow's SGD optimizer tunes our 2 trainable params in the direction of minimum loss.&lt;/p&gt;

&lt;p&gt;After 5 or so epochs, the losses at each epoch start to fluctuate around approximately the same level, this is the point the model has achieved maximum accuracy &amp;amp; minimum loss &amp;amp; the loss won't go lower.&lt;/p&gt;

&lt;p&gt;Now, that the losses are lowest, let's run this model over the house areas &amp;amp; compare how close it predicts the house prices to the actual ones.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not ideal when working with big real-world datasets due to the problem of overfitting, this post will not go further into explaining overfitting &amp;amp; underfitting problems,&lt;/p&gt;

&lt;p&gt;But I'll highly recommend you to go down the rabbit hole of youtube videos &amp;amp; data science articles as to why it is a problem :)&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;house_prices_pred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ml_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;house_prices_pred&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Alright alright alright...&lt;/p&gt;

&lt;p&gt;Let's plot &amp;amp; visualize these predictions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;house_prices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;blue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;house_areas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;house_prices_pred&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;red&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;House areas (sq. ft)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;House prices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Look at that!&lt;/p&gt;

&lt;p&gt;It's almost perfect!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go from here?
&lt;/h2&gt;

&lt;p&gt;Consider going through these resources if you wanna learn more about Deep Learning &amp;amp; TensorFlow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://youtu.be/aircAruvnKk?si=U3_TuOzQUrSsVtLY" rel="noopener noreferrer"&gt;Neural Networks by 3Blue1Brown&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://youtu.be/tpCFfeUEGs8?si=kP_DNo9mCJVqCstT" rel="noopener noreferrer"&gt;Daniel Bourke's TensorFlow Youtube Course&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://youtu.be/ya5NwvKafDk?si=4DkYzu2wyE0zJPSi" rel="noopener noreferrer"&gt;Daniel Bourke's Guide to Machine Learning&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, be sure to give this post a ❤️ to let the DEV Community know this post is good enough :)&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>📈 Analy - My Latest OSS Project &amp; Documenting My Experience w/ #buildinpublic!</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Wed, 15 Mar 2023 21:22:56 +0000</pubDate>
      <link>https://dev.to/gohashira/analy-my-latest-oss-project-documenting-my-experience-w-buildinpublic-3da3</link>
      <guid>https://dev.to/gohashira/analy-my-latest-oss-project-documenting-my-experience-w-buildinpublic-3da3</guid>
      <description>&lt;p&gt;Analy is an open-source tracker &amp;amp; dashboard for website analytics.&lt;/p&gt;

&lt;p&gt;I've been building this project in public on Twitter for quite a while now (got serious with it around mid-January).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And, so far I've been enjoying the journey!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Moreover, the product itself is fundamentally in working condition (both tracker script &amp;amp; dashboard web app)&lt;/p&gt;

&lt;p&gt;In this post, I'll be talking about how I've been making decisions as I coded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with Remix (w/ TypeScript obviously!)
&lt;/h2&gt;

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

&lt;p&gt;I've been always trying to get my hands on Remix.js until I got the idea for this project &amp;amp; it seemed like a perfect situation to try remix building a real-world project.&lt;/p&gt;

&lt;p&gt;It is an interesting framework that had a sort of upper hand in the JS framework market (until Next.js 13 showed up) with Developer-friendly features like Router outlets, layouts, type-safe loaders/actions along with convenient hooks like &lt;code&gt;useLoaderData&lt;/code&gt;, &lt;code&gt;useTransition&lt;/code&gt;, etc. to access data.&lt;/p&gt;

&lt;p&gt;After choosing the desired framework, I looked for which UI library to flavour it with.&lt;/p&gt;

&lt;p&gt;Options that appealed the most to me were ChakraUI &amp;amp; Tailwind due to Chakra's vast library of rich components &amp;amp; well, tailwind being... tailwind.&lt;/p&gt;

&lt;p&gt;For the most part, Tailwind &amp;amp; Chakra worked together like a charm, but there was one disadvantage to using CharkaUI, &lt;strong&gt;Its bundle size&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;And to this day I continue to use ChakraUI simply because I haven't found any better UI library with smaller-sized tree-shakeable components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;—&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Fast forward a month —&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The dashboard app is looking something like this&lt;/p&gt;

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

&lt;p&gt;And I'm starting to struggle with Remix. I prefer readable code over spaghetti code &amp;amp; especially when things are open-source with a teeny bit of chance of someone stopping by to understand or even contribute to the code.&lt;/p&gt;

&lt;p&gt;Remix was making it harder for me to work with API endpoints.&lt;/p&gt;

&lt;p&gt;Fetchers, types of loaders &amp;amp; actions &amp;amp; somewhat lack of flexibility in the framework, in my opinion, were what made me reconsider switching to Next.js.&lt;/p&gt;

&lt;p&gt;So I did, spending the next 2-3 days migrating from Remix over to Next.js.&lt;br&gt;&lt;br&gt;
And not JUST Next.js this time, I migrated the app to the &lt;a href="https://create.t3.gg" rel="noopener noreferrer"&gt;T3 stack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Taking a chance on a library called &lt;a href="https://trpc.io/" rel="noopener noreferrer"&gt;tRPC&lt;/a&gt; (turns out &lt;strong&gt;&lt;em&gt;IT IS AWESOME&lt;/em&gt;&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;Now, I could've been biased here as I've worked with Next.js at every place that required SSR and known it more than any other framework so I may have been accustomed to the flexibility &amp;amp; freedom you get with it.&lt;/p&gt;

&lt;p&gt;And tbh, Remix felt somewhat opinionated and I honestly was looking for something opinionated too (the one on the extreme side is &lt;a href="https://redwoodjs.com/" rel="noopener noreferrer"&gt;Redwood.js&lt;/a&gt;), but after using it, I realized that I don't agree with many of these opinions (e.g Angular) &amp;amp; thus, Next.js felt much better.&lt;/p&gt;
&lt;h2&gt;
  
  
  Migrating to Create-T3-App
&lt;/h2&gt;

&lt;p&gt;Let's move our focus towards why I chose specifically T3 stack and not just went with file-based API endpoint and then call them with fetch or even React query.&lt;/p&gt;

&lt;p&gt;You see, when you write API endpoints in separate files &amp;amp; use something like fetch or react-query for more advanced features, you either have to manually define types for the data returned by these endpoints or just roll with the "any" type.&lt;/p&gt;

&lt;p&gt;My goal on the other side, with building this open-source app, is to &lt;strong&gt;&lt;em&gt;make the code as easy to read as possible&lt;/em&gt;&lt;/strong&gt; (along with, of course, making the actual freakin' product)&lt;/p&gt;

&lt;p&gt;This is exactly where tRPC comes into the picture.&lt;/p&gt;

&lt;p&gt;It provides a way to infer the type of data returned by all the API routes you define in it which is exactly what I was looking for in a framework/library.&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Because, TypeScript is best utilized NOT with manual type definitions, but with inferred types.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Talking more about tRPC, I love its 2 features that give a massive productivity boost:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Request Batching&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
tRPC groups requests while sending from the client to the server, this means it will ping your tRPC server endpoint only once for queries made at the same time and avoids duplicate requests.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Therefore, I can query the same route in multiple nested components and returned data will be shared among them instead of being fetched multiple times.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React query&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I absolutely love how react-query handles the querying state &amp;amp; manages it and with tRPC, I can access the &lt;code&gt;useQuery&lt;/code&gt; of react-query effortlessly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, I felt lazy setting up TypeScript, Tailwind, tRPC &amp;amp; Prisma all by myself so I created the Next.js app with &lt;code&gt;create-t3-app&lt;/code&gt; and it provided me with the basic boilerplate code to get me started.&lt;/p&gt;

&lt;p&gt;It's been almost a month since I started to make some real progress with the t3 stack &amp;amp; so far, everything has been going really well.&lt;/p&gt;

&lt;p&gt;And because Next when used with tRPC &amp;amp; react-query collectively solve my previous problems in Remix with data-fetching &amp;amp; state, I hope I hold on to this stack for a long time 😊&lt;/p&gt;
&lt;h2&gt;
  
  
  Current State of Analy
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Analy Dashboard
&lt;/h3&gt;

&lt;p&gt;The Analy Dashboard currently track basic analytics like date ranges for page views, the number of sessions &amp;amp; unique page visits along with real-time stats, top visited pages, top referrers and from the past week, user feedback too!&lt;/p&gt;

&lt;p&gt;Here's a Twitter thread I wrote explaining the feedback-collecting functionality&lt;/p&gt;

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

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



&lt;/p&gt;

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

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

&lt;h3&gt;
  
  
  Analy NPM Tracker Script
&lt;/h3&gt;

&lt;p&gt;The script ensures total privacy for the user thus, uses no cookies,&lt;br&gt;&lt;br&gt;
Instead, anonymously identifies users &amp;amp; their sessions with self-generated ids.&lt;/p&gt;

&lt;p&gt;It currently tracks some default events like page loads, new users along with the capability to track custom events with a callable function &lt;code&gt;trackEvent&lt;/code&gt; or via HTML attributes &lt;code&gt;analy-event&lt;/code&gt; &amp;amp; &lt;code&gt;analy-dom-event&lt;/code&gt; to specify the &lt;strong&gt;event name&lt;/strong&gt; &amp;amp; &lt;strong&gt;dom event name&lt;/strong&gt; (e.g "click" or "hover") respectively.&lt;/p&gt;

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

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

&lt;p&gt;Future plans are to integrate advanced features into the dashboard like custom events &amp;amp; session recordings to create &amp;amp; analyze funnels in order to understand more about dropoffs &amp;amp; where those dropoffs are happening.&lt;/p&gt;

&lt;p&gt;Everything I do is posted on my Twitter as threads ✨&lt;/p&gt;




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

&lt;p&gt;I hope you enjoyed this little post about me talking about my experience building my first open-source SaaS product in public - Analy 📈&lt;/p&gt;

&lt;p&gt;I love talking to strangers and my DMs are always open to interesting ideas &amp;amp; feedback 🤗&lt;/p&gt;

&lt;p&gt;Some relevant links are thrown here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Twitter - &lt;a href="https://twitter.com/BhardwajKuvam" rel="noopener noreferrer"&gt;BhardwajKuvam&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analy Dashboard Source Code - &lt;a href="https://github.com/kuvamdazeus/analy-dashboard" rel="noopener noreferrer"&gt;kuvamdazeus/analy-dashboard&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analy Tracker Script Source Code - &lt;a href="https://github.com/kuvamdazeus/analy-dashboard" rel="noopener noreferrer"&gt;kuvamdazeus/analy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>3 Steps to OAuth (with Code &amp; Examples!)</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Fri, 17 Feb 2023 16:29:36 +0000</pubDate>
      <link>https://dev.to/gohashira/3-steps-to-oauth-with-code-examples-n99</link>
      <guid>https://dev.to/gohashira/3-steps-to-oauth-with-code-examples-n99</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So... what is this... "OAuth" huh?&lt;br&gt;&lt;br&gt;
This is what they say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OAuth is an open-standard authorization &lt;strong&gt;protocol&lt;/strong&gt; or framework that provides applications the ability for secure designated access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gibberish, let me break this down in layman's terms&lt;/p&gt;

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

&lt;p&gt;This is DEV's login page ☝🏻&lt;/p&gt;

&lt;p&gt;The buttons you see here - "Continue with Apple / Forem / GitHub / Twitter" use &lt;strong&gt;The OAuth Flow&lt;/strong&gt; to redirect you to a third-party service that will identify you &lt;em&gt;for&lt;/em&gt; Dev.to (&lt;em&gt;while you allow yourself to be identified by this service &amp;amp; give read access of your profile to Dev.to&lt;/em&gt;) and this service will then redirect you back to Dev.to's website saying "&lt;em&gt;here are the credentials of this person who wants to signup on your website, we've verified him, you're good to go&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;In this post, we'll implement this OAuth flow using &lt;strong&gt;GitHub&lt;/strong&gt; &amp;amp; &lt;strong&gt;NextJS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's do this!&lt;/p&gt;
&lt;h2&gt;
  
  
  Idea Behind OAuth
&lt;/h2&gt;

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

&lt;p&gt;Let's say you're making a tweet scheduler app,&lt;br&gt;&lt;br&gt;
They come on your app, write a tweet &amp;amp; schedule it,&lt;br&gt;&lt;br&gt;
It's your job now to save that tweet &amp;amp; later post it on Twitter &lt;em&gt;on their behalf.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You're in a dilemma now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;On the one hand, you can't ask the user for their account name &amp;amp; password just to make a tweet because they wouldn't trust your app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the other hand, if you go to Twitter saying "hey Twitter, a user with the name &lt;code&gt;@johndoe&lt;/code&gt; wants to post this..."&lt;br&gt;&lt;br&gt;
Twitter simply wouldn't allow that because anyone can tweet on anyone else's behalf then!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the &lt;em&gt;Standard OAuth Protocol&lt;/em&gt; comes in.&lt;/p&gt;

&lt;p&gt;You redirect the user to Twitter's website and indicate what you want access for, user now has the power to authorize your app or disallow it from having tweet post access to your account,&lt;br&gt;&lt;br&gt;
Twitter will then accordingly redirect the user back to your website giving you either &lt;code&gt;code&lt;/code&gt; or an error.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;code&lt;/code&gt; is a string of utf-8 characters that Twitter generates and it is used to Identify:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Your app&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The permissions user has agreed to authorize your app.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This flow is kept a standard for all services that can help identify people &amp;amp; authorize other apps on users' behalf to read/write data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Enough talking Let's Code!
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command will create a starter NextJS app,&lt;br&gt;&lt;br&gt;
Name your app, select JavaScript or TypeScript (doesn't really matter here, I went with TypeScript),&lt;br&gt;&lt;br&gt;
And you're all set up!&lt;/p&gt;
&lt;h3&gt;
  
  
  Why did I choose NextJS?
&lt;/h3&gt;

&lt;p&gt;Well you see, implementing OAuth requires a server-side node API endpoint and with this framework, we can have all our server-side (Node) &amp;amp; client-side (React) logic in one place.&lt;/p&gt;

&lt;p&gt;You're welcome to use any other backend framework here as long as it follows the same logic we'll be using in this post.&lt;/p&gt;

&lt;p&gt;There remains one more question: "Why do I need a server-side endpoint anyway?" to which I'd suggest you to read along as it unfolds.&lt;br&gt;&lt;br&gt;
(hint: for secure communication between server &amp;amp; oauth service)&lt;/p&gt;

&lt;p&gt;Now, I need you to head over to your GitHub account &amp;gt; Settings &amp;gt; Developer Settings &amp;gt; OAuth Apps and Create a new oauth app&lt;/p&gt;

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

&lt;p&gt;The most important field here is the "Authorization Callback URL" which we set to our server-side API endpoint - &lt;code&gt;http://localhost:3000/api/auth&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We are to make a file &lt;code&gt;auth.ts&lt;/code&gt; under the &lt;code&gt;api&lt;/code&gt; folder yet.&lt;/p&gt;

&lt;p&gt;This is the URL GitHub will redirect the user to, after the user &lt;em&gt;authorizes&lt;/em&gt; or &lt;em&gt;rejects&lt;/em&gt; your authorization request.&lt;/p&gt;

&lt;p&gt;Go ahead, register your application &amp;amp; then generate the client secret&lt;/p&gt;

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

&lt;p&gt;GitHub needs the client id &amp;amp; client secret to identify your app and redirect the user to the appropriate callback URLs&lt;/p&gt;

&lt;p&gt;Now, let us head over to the NextJS app &amp;amp; create a &lt;code&gt;.env&lt;/code&gt; to store client id &amp;amp; secret in one place.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why store secrets in a .env file instead of let's say a "config.js" file?
&lt;/h3&gt;

&lt;p&gt;The first &amp;amp; foremost reason is that you can add &lt;code&gt;.env&lt;/code&gt; to a &lt;code&gt;.gitignore&lt;/code&gt; and it will be skipped by git when hosting the code on GitHub.&lt;/p&gt;

&lt;p&gt;Now, when you deploy the code to some service like Vercel, they ask for "Environment Variables" and you can just add the client id &amp;amp; secret over there.&lt;/p&gt;

&lt;p&gt;This serves 2 important purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;No one else can steal your GitHub OAuth credentials from code (pretty evident)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You'll have to create another oauth app (&lt;em&gt;this is GitHub-specific by the way&lt;/em&gt;) with the authorization callback URL set to your site's hosted URL in GitHub because you'd be hosting your web app &amp;amp; if you use your old OAuth credentials, it would simply redirect the user to &lt;code&gt;http://localhost:3000/api/auth&lt;/code&gt; instead of &lt;code&gt;https://your-hosted-app-url.vercel.app/api/auth&lt;/code&gt; on authorization requests from the hosted version.&lt;br&gt;&lt;br&gt;
(This is why &lt;code&gt;.env&lt;/code&gt; files are used extensively for &lt;em&gt;different environments&lt;/em&gt;!)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg609jcro37xc9l9assy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg609jcro37xc9l9assy.png" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;" oi oi oi oi oi.... why's there a&lt;/strong&gt; &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; &lt;strong&gt;there? "&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Oh, you caught me slippin' that one, eh!&lt;/p&gt;

&lt;p&gt;As you know, adding &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; after the env file variable names tell NextJS that we wanna "expose" that env variable to the client side React app, Not adding this prefix in a variable means that we don't wanna use that variable or "expose" it on the client side.&lt;/p&gt;

&lt;p&gt;This is where the role of the server-side API endpoint comes in,&lt;br&gt;&lt;br&gt;
You see, the GitHub client secret is like a password &amp;amp; the client id, you can think of it as a username to help GitHub identify your app.&lt;/p&gt;

&lt;p&gt;You can show your username to the public but it wouldn't be preferable to publicly expose your password just like the username,&lt;br&gt;&lt;br&gt;
If we add &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; in front of a sensitive env file variable, NextJS while building your app bundle (i.e the final javascript file to be sent to the user's browser) will include that variable in the file source code too.&lt;/p&gt;

&lt;p&gt;If you're patient enough to read through the javascript responses of a page, you can easily find it and someone with malicious intents can easily exploit this exposed variable!&lt;/p&gt;

&lt;p&gt;However, you can still use the env variable without the &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; but only on the server side.&lt;/p&gt;

&lt;p&gt;This is why we'll be using the server for all the communications with GitHub API which includes sending client secret along with our requests.&lt;/p&gt;

&lt;p&gt;Honestly idk why I named this section "&lt;em&gt;Enough talking Let's Code!&lt;/em&gt;" cuz we're still talking, but promise me, the next line will be code!&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;Hah! it wasn't 🤣&lt;/p&gt;

&lt;p&gt;Jokes apart, let's start by building the URL that GitHub requires our app to redirect users in order to start the authorization process.&lt;/p&gt;

&lt;p&gt;From here, I'll be referring to GitHub's own docs for performing OAuth requests, you can check them out here👇🏻&lt;br&gt;&lt;br&gt;
&lt;a href="https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps" rel="noopener noreferrer"&gt;https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Redirect User to Authorization URL
&lt;/h3&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;oauthUri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://github.com/login/oauth/authorize?client_id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_GH_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;scope=user:email,read:user&amp;amp;redirect_uri=http://localhost:3000/api/auth`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For the sake of not talking extra, I've hard-coded the &lt;code&gt;redirect_uri&lt;/code&gt; to &lt;code&gt;http://localhost:3000/api/auth&lt;/code&gt; that should actually be stored in a &lt;code&gt;.env&lt;/code&gt; file and changed according to the environments in which the app is being hosted and the associated authorization callback URL.&lt;/p&gt;

&lt;p&gt;Coming to the &lt;code&gt;scope&lt;/code&gt; param of the URL, we've provided a list of scopes: &lt;strong&gt;read:user&lt;/strong&gt; &amp;amp; &lt;strong&gt;user:email&lt;/strong&gt; to it which means we want read access to the user's details (username, name, etc.) &amp;amp; their email.&lt;/p&gt;

&lt;p&gt;The code looks something like this:&lt;/p&gt;

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

&lt;p&gt;After running the app in dev mode &amp;amp; clicking the link "Login with GitHub" on the page, we are redirected to this page:&lt;/p&gt;

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

&lt;p&gt;Have a close look at this page, it clearly describes an App named &lt;em&gt;Test&lt;/em&gt; made by a GitHub user &lt;em&gt;Kuvam Bhardwaj&lt;/em&gt; wants your GitHub profile data (email &amp;amp; other public info) and clearly states the access is read-only.&lt;/p&gt;

&lt;p&gt;Refer to this url for more info on all available &lt;code&gt;scopes&lt;/code&gt; 👇🏻&lt;br&gt;&lt;br&gt;
&lt;a href="https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps" rel="noopener noreferrer"&gt;https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing this page is generally a big relief as we didn't mess up the setup in GitHub developer settings ✌🏻&lt;/p&gt;

&lt;p&gt;Authorize the app &amp;amp; if you correctly put the URL in the authorization callback URL in GitHub settings, you should be redirected to the specified URL (&lt;code&gt;/api/auth&lt;/code&gt;)&lt;/p&gt;

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

&lt;p&gt;Notice the URL address bar contains some kind of &lt;code&gt;code&lt;/code&gt; following a string of random characters,&lt;br&gt;&lt;br&gt;
This, ladies &amp;amp; gentlemen, is how victory looks, a string of hexadecimal characters 🥂&lt;/p&gt;

&lt;p&gt;Let's now create a file named &lt;code&gt;auth.ts&lt;/code&gt; under &lt;code&gt;api&lt;/code&gt; folder to actually handle this victory!&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Exchanging the Code for an Access token
&lt;/h3&gt;

&lt;p&gt;After authorizing, GitHub redirects the user to our specified URL which is actually a server-side API endpoint.&lt;/p&gt;

&lt;p&gt;This API endpoint will make a POST request to GitHub's OAuth API sending the obtained &lt;code&gt;code&lt;/code&gt; and client secret as the payload, in response, we'll probably receive an &lt;code&gt;access_token&lt;/code&gt; if the &lt;code&gt;code&lt;/code&gt; was valid.&lt;/p&gt;

&lt;p&gt;On receiving the &lt;code&gt;access_token&lt;/code&gt; we can start making requests on behalf of the user, in this case, getting their email &amp;amp; public info.&lt;/p&gt;

&lt;p&gt;If the scopes we previously specified were of editing user's personal data, followers management or even repo creation/deletion, we would be able to do that too with this &lt;code&gt;access_token&lt;/code&gt; though you might have to search the docs for finding a suitable API endpoint that does that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You would get errors if you make requests to API endpoints that require additional scopes than you've specified.&lt;/p&gt;

&lt;p&gt;Referring GitHub's API docs is the best way to know what endpoints require which scopes.&lt;/p&gt;

&lt;p&gt;Or... just... refer to docs in general... they're helpful!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;In our simple example, we'll simply exchange&lt;/strong&gt; &lt;code&gt;code&lt;/code&gt; &lt;strong&gt;for&lt;/strong&gt; &lt;code&gt;access_token&lt;/code&gt;&lt;strong&gt;, fetch the user's profile data with it, print it on the console and redirect the user to the homepage.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This could easily be scaled to do obvious things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;save the user's data in a database after fetch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;set a cookie to identify the user by their database ID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;redirect to some dashboard or some other personalized page after authenticating them with cookies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let us look at the code for exchanging the &lt;code&gt;code&lt;/code&gt; for &lt;code&gt;acess_token&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Ahem... please excuse my copilot prompts...&lt;/p&gt;

&lt;p&gt;In the above code, when the user lands on &lt;code&gt;/api/auth&lt;/code&gt; we grab the &lt;code&gt;code&lt;/code&gt; embedded in the URL &amp;amp; send it in the POST request body along with other variables like &lt;code&gt;client_id&lt;/code&gt; &amp;amp; &lt;code&gt;client_secret&lt;/code&gt; to get back the &lt;code&gt;access_token&lt;/code&gt; from GitHub.&lt;/p&gt;

&lt;p&gt;Headers in the fetch request, as hinted by their name, say to GitHub's API that we are sending a body in JSON format (&lt;code&gt;Content-Type&lt;/code&gt;) &amp;amp; we want a response in a JSON format (&lt;code&gt;Accept&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For some reason, GitHub defaults to sending a string looking something like this unless we explicitly provide the &lt;code&gt;Accept&lt;/code&gt; header in the POST request&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&amp;amp;scope=repo%2Cgist&amp;amp;token_type=bearer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our work is partially done now, we have the &lt;code&gt;access_token&lt;/code&gt; and just need to use this and get the user's profile details on their behalf.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Use the Access token to Perform Actions on user's behalf
&lt;/h3&gt;

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

&lt;p&gt;After getting &lt;code&gt;access_token&lt;/code&gt; we use it in the header as &lt;code&gt;Authorization: Bearer access-token...&lt;/code&gt; &amp;amp; request the GitHub API to grant us their profile data.&lt;/p&gt;

&lt;p&gt;Let's now click on the "Login with GitHub" button on the index page again!&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrihd55jc48e2iwjpcei.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrihd55jc48e2iwjpcei.gif" alt="touching myself ryan reynolds GIF by Deadpool's Fun Sack" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generalizing GitHub-specific Patterns for other OAuth Providers
&lt;/h2&gt;

&lt;p&gt;So, until now we've been very specific to GitHub, but if you refer to docs of other OAuth providers like LinkedIn or Google or Facebook,&lt;/p&gt;

&lt;p&gt;You'll notice this pattern where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You get your personalized client id &amp;amp; client secret&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redirect the user to a link with the client id, redirect uri &amp;amp; scopes or access permissions embedded in it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user either authorizes or cancels the authorization request and you get the user redirected to your site with an error or some kind of code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You then exchange this code for an &lt;code&gt;access_token&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, you start making requests to the service on behalf of the user with the &lt;code&gt;access_token&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you've used any BaaS platform like firebase or supabase before, then you can distinctively point out what's happening!&lt;/p&gt;

&lt;p&gt;For example here in supabase when I go ahead to setup Authentication with Social login via Google:&lt;/p&gt;

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

&lt;p&gt;It asks me to enter my client id, and client secret &amp;amp; gives me a URL to add in redirect URIs in Google's OAuth setup process,&lt;/p&gt;

&lt;p&gt;Supabase will manage the rest on its own, all the callbacks, redirecting users to your app, everything!&lt;/p&gt;

&lt;p&gt;I might have to add that you still need to provide YOUR APP's URL so that supabase itself can redirect the user to your web app post-authentication.&lt;/p&gt;

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

&lt;p&gt;Here's Google's OAuth setup screen for reference&lt;/p&gt;

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

&lt;p&gt;And you might as well find the docs that list all the scopes for authorization along with all the minute details that are Google-specific!&lt;/p&gt;

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




&lt;p&gt;Thanks for reading!&lt;br&gt;&lt;br&gt;
If you liked the article, consider dropping some emojis ♥️🔥💯✨&lt;/p&gt;

&lt;p&gt;But, if you loved it?&lt;br&gt;&lt;br&gt;
I post about the web every day on Twitter 👉🏻 &lt;a href="https://twitter.com/BhardwajKuvam" rel="noopener noreferrer"&gt;bhardwajkuvam&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Consider giving me a follow there ♥️&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>yeetboard - A fun Multi-Player Whiteboarding App</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Sat, 27 Aug 2022 18:26:01 +0000</pubDate>
      <link>https://dev.to/gohashira/yeetboard-a-fun-multi-player-whiteboarding-app-4acf</link>
      <guid>https://dev.to/gohashira/yeetboard-a-fun-multi-player-whiteboarding-app-4acf</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;I've always been interested in applications which are capable of providing collaborative experiences to user like the VSCode's Live Share, or Figma's interactive &amp;amp; beautiful collaborative UI.&lt;/p&gt;

&lt;p&gt;Haven't been able to make a collaborative app, I was motivated enough to take on this challenge of making an online whiteboarding app where multiple users can join in on sessions &amp;amp; collaborate or even brainstorm on a plain canvas.&lt;/p&gt;

&lt;p&gt;So, here, in this project, I've attempted to give users freedom to draw, shapes or free-hand. With customisability of the elements they create on empty canvas while being able to collaborate with friends with just ONE-CLICK!&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Language Used: JS/TS/Node.js
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Link to Code: &lt;a href="https://github.com/kuvamdazeus/yeetboard" rel="noopener noreferrer"&gt;https://github.com/kuvamdazeus/yeetboard&lt;/a&gt;
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Demo Video Showing Features: &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/RPY1qSU9tjw"&gt;
&lt;/iframe&gt;

&lt;/h3&gt;

&lt;h3&gt;
  
  
  Collaborators: None
&lt;/h3&gt;




&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Check out &lt;a href="https://redis.io/docs/stack/get-started/clients/#high-level-client-libraries" rel="noopener noreferrer"&gt;Redis OM&lt;/a&gt;, client libraries for working with Redis as a multi-model database.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Use &lt;a href="https://redis.info/redisinsight" rel="noopener noreferrer"&gt;RedisInsight&lt;/a&gt; to visualize your data in Redis.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sign up for a &lt;a href="https://redis.info/try-free-dev-to" rel="noopener noreferrer"&gt;free Redis database&lt;/a&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redishackathon</category>
    </item>
    <item>
      <title>I was creating Forms the wrong way all along in React.js 🤔</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Mon, 01 Aug 2022 10:19:41 +0000</pubDate>
      <link>https://dev.to/gohashira/i-was-creating-forms-the-wrong-way-all-along-in-reactjs-hl3</link>
      <guid>https://dev.to/gohashira/i-was-creating-forms-the-wrong-way-all-along-in-reactjs-hl3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When I was creating a signup form, I found myself creating dozens of useStates &amp;amp; then creating dozens of onChange handlers for those useStates. Something like this 🤮&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659161853469%2FkpTlwW5zm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659161853469%2FkpTlwW5zm.png" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Man I feel sleepy even writing this for illustration!&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Also, you're welcome, for blasting your eyes with that monstrous &lt;em&gt;One Light&lt;/em&gt; theme code snippet. Some amount of white is good for attention aye! 😉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So... you get the point, In this post, I'll be trying to solve this problem in an elegant manner (certainly not the BS I did in my &lt;a href="https://kuvambhardwaj.hashnode.dev/how-not-to-use-dozens-of-usestates-for-a-big-reactjs-form" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, making a buggy React Form component which no one even bothers to have a look at!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Let's Get Started!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// NOT a even a SINGLE useState babyyyyyyy! 😎&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;inputObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// convert the FormData object to a JSON object&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submitForm&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can try this code &amp;amp; tinker with it in the same browser as you're viewing this post, thanks to &lt;strong&gt;codesandbox&lt;/strong&gt; (&lt;a href="https://codesandbox.io/s/formdata-forked-ll8jbs?file=/src/App.js:0-645" rel="noopener noreferrer"&gt;code link&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For my beginner friends, who are new to React, what we did here was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wrap the input fields in an actual HTML &lt;code&gt;form&lt;/code&gt; element&lt;/li&gt;
&lt;li&gt;define the &lt;code&gt;name&lt;/code&gt; attribute of each of the input fields (can be anything, HTML uses this attribute to name the input value against it)&lt;/li&gt;
&lt;li&gt;create a button with no &lt;code&gt;onClick&lt;/code&gt; handler but a &lt;code&gt;type&lt;/code&gt; attribute set to &lt;code&gt;'submit'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;define an &lt;code&gt;onSubmit&lt;/code&gt; handler under the &lt;code&gt;form&lt;/code&gt; element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the user has done typing their details in the input, clicking on the button with &lt;code&gt;type='submit'&lt;/code&gt; declared in the form, will cause the HTML &lt;code&gt;form&lt;/code&gt; element to call its &lt;code&gt;onSubmit&lt;/code&gt; handler i.e our &lt;code&gt;submitForm&lt;/code&gt; 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// 2&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 3&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// convert the FormData object to a JSON object&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we've done 3 things here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;call the &lt;code&gt;preventDefault&lt;/code&gt; method of the HTML &lt;code&gt;FormEvent&lt;/code&gt; type, passed as an argument into our function by the HTML Goddess herself (we named it &lt;code&gt;e&lt;/code&gt;). This function prevents the form from continuing its default behaviour after submission which includes automatically making a GET request to the same page's URL with the form input values as payload AND reloading the page (we don't want that because &lt;strong&gt;we're defining our own form submit logic whose functioning will be interrupted by a page reload&lt;/strong&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the form element (referenced as &lt;code&gt;e.target&lt;/code&gt;) in a &lt;code&gt;FormData&lt;/code&gt; constructor &amp;amp; store it in our &lt;code&gt;formData&lt;/code&gt; constant. &lt;br&gt;
&lt;strong&gt;This will take the input elements and parse them into key-value pairs&lt;/strong&gt; where the key is what we defined in the &lt;code&gt;name&lt;/code&gt; attribute against our inputs &amp;amp; the value will be their corresponding input text. All the different input text values can be retrieved using their name, something like this:&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="c1"&gt;// quite similar to the map syntax to get a key ( map.get("key") )&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&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;Isn't that quite magical AND elegant? HTML does all the work for you from parsing the form input values to collecting the data &amp;amp; returning it in a map-like structure 🪄.=&lt;/p&gt;

&lt;p&gt;3.Last but not least, we convert the &lt;code&gt;FormData&lt;/code&gt; object which has our input values, to a plain JavaScript object with &lt;code&gt;Object.fromEntries( ... )&lt;/code&gt;. Logging the, now created object, gives this output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659337512578%2FDKtxbevEI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659337512578%2FDKtxbevEI.png" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IT WORKS!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BUT! and that's a big but (pun intended), the &lt;strong&gt;cons of this approach is that you CAN'T write &lt;em&gt;Controlled Inputs&lt;/em&gt;&lt;/strong&gt;. For that, you HAVE TO declare a &lt;code&gt;useState&lt;/code&gt; &amp;amp; It's corresponding &lt;code&gt;onChange&lt;/code&gt; handler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What the hell is a controlled Input?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have a look at this example&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659341263223%2FXQtVN3N9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659341263223%2FXQtVN3N9f.png" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a controlled input in React js, but for inputs like this, we can use the hybrid approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define all the inputs in a form&lt;/li&gt;
&lt;li&gt;Write &lt;code&gt;useState&lt;/code&gt; &amp;amp; &lt;code&gt;onChange&lt;/code&gt; handler ONLY for those inputs that are controlled&lt;/li&gt;
&lt;li&gt;Then, manually set values in the formData to those controlled state variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659341686397%2FC0Bo4vmnL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659341686397%2FC0Bo4vmnL.png" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/qPcX2mzk3NmjC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/qPcX2mzk3NmjC/giphy.gif" width="450" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;P.S:&lt;br&gt;
Seeing HTML automatically handling inputs for us appears to be some kind of magic and to be honest, I hate when magic is occurring BUT some amount of magic is bearable for the sake of making the developer experience good 👌🏻&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Aaaand... that's a wrap!&lt;br&gt;
Like this post, if you liked it 🙃&lt;br&gt;&lt;br&gt;
But if you loved it? man you gotta follow me on &lt;a href="https://twitter.com/bhardwajkuvam" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 😉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bye for now!&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The useEffect hook in ReactJS</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Thu, 28 Jul 2022 11:56:03 +0000</pubDate>
      <link>https://dev.to/gohashira/the-useeffect-hook-in-reactjs-2dna</link>
      <guid>https://dev.to/gohashira/the-useeffect-hook-in-reactjs-2dna</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So, when I was a kid, my mama told me&lt;br&gt;
"The new React hooks API is really cool, the &lt;code&gt;useEffect&lt;/code&gt; hook replaced &lt;code&gt;componentDidMount&lt;/code&gt; &amp;amp; &lt;code&gt;componentDidUpdate&lt;/code&gt; of the Class API"&lt;/p&gt;

&lt;p&gt;I wanted to ask her more about it but she got busy optimizing her React component that was re-rendering multiple times.&lt;/p&gt;

&lt;p&gt;When I got older, I learned more about React &amp;amp; these hooks API, and today I'll try explaining to YOU what my mom didn't explain to ME &amp;amp; Probably your mom didn't too — &lt;strong&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;So, here I created a React app in &lt;em&gt;codesandbox&lt;/em&gt; on my browser&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659006078804%2FPICp8H_WM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1659006078804%2FPICp8H_WM.png" width="800" height="940"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yup! My Web browser!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the &lt;a href="https://codesandbox.io/s/cranky-mcclintock-l5he9q" rel="noopener noreferrer"&gt;link&lt;/a&gt;, interact with it yourself!&lt;/p&gt;

&lt;p&gt;For those of you lazy folks who don't wanna go anywhere, here's the code 🫠&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="c1"&gt;// App.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&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;h3&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;counter&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;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prevValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Increment&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Simple? huh...&lt;/p&gt;

&lt;p&gt;Only 1 state variable defined &lt;code&gt;counter&lt;/code&gt; which is being incremented at every button tap by &lt;code&gt;setCounter&lt;/code&gt;, also a &lt;code&gt;useEffect&lt;/code&gt; with &lt;code&gt;console.log(counter)&lt;/code&gt; in its function body, nothing kubernetes!&lt;/p&gt;

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

&lt;p&gt;Let's now focus on the &lt;code&gt;useEffect&lt;/code&gt; defined here&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&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;As evident, by the code, the hook takes a function which it'll internally call at "times". Those "times" can be the component re-render, initial component mount or any state update call which causes the component to, of course, re-render.&lt;/p&gt;

&lt;p&gt;After running this code, I tap on the increment button 3 times &amp;amp; these are the console logs I get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658992237044%2FIOOXLZTEg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658992237044%2FIOOXLZTEg.png" width="758" height="1304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤔 Hmm... looks like, this particular &lt;code&gt;useEffect&lt;/code&gt; ran on these occasions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the component is first mounted ( printed "0" to the console )&lt;/li&gt;
&lt;li&gt;When I tap the increment button or in short, the state update occurred&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, lets change the &lt;code&gt;useEffect&lt;/code&gt; to 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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we're now passing an empty array "[]" (also known as &lt;strong&gt;&lt;em&gt;Dependency Array&lt;/em&gt;&lt;/strong&gt;) as the second argument to the &lt;code&gt;useEffect&lt;/code&gt; hook&lt;/p&gt;

&lt;p&gt;Running the code again, I tap on the increment button 3 times &amp;amp; these are the console log I get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658992644563%2Fwc1nrSXHo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658992644563%2Fwc1nrSXHo.png" width="760" height="1386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, so this time the &lt;code&gt;useEffect&lt;/code&gt; ran only at the time of mount of the component &amp;amp; NOT at the time of state update... INTERESTING! 🧐&lt;br&gt;
&lt;a href="https://i.giphy.com/media/RhPvGbWK78A0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RhPvGbWK78A0/giphy.gif" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, again! let us edit the code once more, bear with me :)&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="c1"&gt;//App.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;anotherCounter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAnotherCounter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;COUNTER VALUE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&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;h3&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;counter&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;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prevValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Increment&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;h3&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;anotherCounter&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;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setAnotherCounter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prevValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Random&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="nx"&gt;Update&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Alright, so... I've done 3 things here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the &lt;code&gt;counter&lt;/code&gt; state variable to the previously left empty array&lt;/li&gt;
&lt;li&gt;Add another state variable &amp;amp; called it &lt;code&gt;anotherCounter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the JSX to display &amp;amp; increment the &lt;code&gt;anotherCounter&lt;/code&gt; variable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll now run the app &amp;amp; click on the "Increment" button 3 times &amp;amp; "Random State Update" button 2 times and these are the console logs I got&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658993740296%2FcfnHngUBa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658993740296%2FcfnHngUBa.png" width="756" height="1386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oohoo! so now the &lt;code&gt;useEffect&lt;/code&gt; hook is firing our function SELECTIVELY when the &lt;code&gt;counter&lt;/code&gt; state is changed and not when &lt;code&gt;anotherCounter&lt;/code&gt; state is changed, although, the &lt;code&gt;setAnotherCounter&lt;/code&gt; is causing the component to re-render &amp;amp; update the &lt;code&gt;anotherCounter&lt;/code&gt; to the UI.&lt;/p&gt;

&lt;p&gt;Now, you've probably understood to some extent what that "empty array ( [] )" meant...&lt;/p&gt;

&lt;p&gt;NICE!&lt;/p&gt;

&lt;p&gt;Let us recap what &lt;code&gt;useEffect&lt;/code&gt; when correctly written can do!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;With the dependency array left empty, the &lt;code&gt;useEffect&lt;/code&gt; will run the callback function (defined by us) ONLY ONCE &lt;em&gt;right after the component renders UI&lt;/em&gt;. (equivalent to &lt;code&gt;componentDidMount&lt;/code&gt; in class components)
&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/*
    Here, state initialization logic can be added
    OR, fetch requests to Backend servers can be made for data-fetching
    As this is only running once, you're not bombarding your server

  */&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;With state variable(s) given in the dependency array, the &lt;code&gt;useEffect&lt;/code&gt; will run when the component first mounts &amp;amp; will also be running whenever the given state variables are changed
&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;dependencies&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;With no dependency array defined as its second argument, the hook will call our function on EVERY SUBSEQUENT component re-render
&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// I don't prefer this but yeah! it's there if you want to use it!&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Aaaand... that's a wrap!&lt;br&gt;
Like this post, if you liked it 🙃&lt;br&gt;&lt;br&gt;
But if you loved it? man you gotta follow me on &lt;a href="https://twitter.com/bhardwajkuvam" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 😉&lt;/p&gt;

&lt;p&gt;Feedback is much appreciated! 🤗&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqak088la8k1cdzcytgp7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqak088la8k1cdzcytgp7.gif" width="390" height="220"&gt;&lt;/a&gt;&lt;br&gt;
Meet you another day with another post ⚡️&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>How To Mint NFTs in Solidity</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Thu, 21 Apr 2022 08:34:49 +0000</pubDate>
      <link>https://dev.to/gohashira/how-to-mint-nfts-in-solidity-559l</link>
      <guid>https://dev.to/gohashira/how-to-mint-nfts-in-solidity-559l</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Among this "web3" and blockchain hype, I decided to venture into the dev side of the hype. Initialized hardhat project, opened my editor &amp;amp; struck the keyboard keys until I got to a working thingy &amp;amp; in this post I'll be walking you through how to make one &amp;amp; share what I learned along the way.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Let's get started!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A short note to all my beginner friends, this post is totally suited for you &amp;amp; I'll be walking you through, *&lt;/em&gt;&lt;em&gt;LIKE A BABY&lt;/em&gt;** on how to write these smart contracts*&lt;/p&gt;

&lt;p&gt;Before jumping on to the code, let us just zoom out for a second &amp;amp; ask:&lt;br&gt;
&lt;strong&gt;"What are smart contracts"&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;"What are NFTs"&lt;/strong&gt; and&lt;br&gt;
&lt;strong&gt;"What are Tokens anyways"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Smart Contract is simply some code, written in the solidity programming language (Solidity is for Ethereum Blockchain. Other blockchains may require something different if they have smart contracts), deployed on the Ethereum Blockchain to perform certain operations defined in the code itself&lt;/strong&gt;. You see, the Ethereum Blockchain consists of thousands of decentralized compute nodes sitting &amp;amp; crunching numbers to keep the blockchain active. &lt;strong&gt;When you deploy code on the blockchain, you're required to provide incentives or fees to encourage nodes to process your deployment transaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Also, anyone (a user with some wallet address) calling your smart contract function &lt;strong&gt;which causes some state change in your code (like modifying the value of a variable in your code), will have to give a fee.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This fee is known as &lt;strong&gt;&lt;em&gt;GAS FEE&lt;/em&gt;&lt;/strong&gt;, &lt;em&gt;similar to you providing 💰 to AWS&lt;/em&gt; for their lambda functions.&lt;/p&gt;

&lt;p&gt;A Token on the other hand is SOMETHING on the blockchain, with which these smart contracts interact, creating, manipulating, or destroying them. That SOMETHING can itself be anything saved in a smart contract's state, some text, number, etc. while REPRESENTING numerous things like an image, currency, or even a virtual girlfriend! the possibilities are endless!&lt;/p&gt;

&lt;p&gt;Let's see an example of a smart contract written in solidity, which maintains a record of "who called the smart contract how many times?"&lt;/p&gt;

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

&lt;p&gt;In this solidity code or Ethereum smart contract, we have a map (a data structure that is used to maintain key-value pairs in solidity, here the key is user address &amp;amp; value is a positive 256-bit integer) &lt;code&gt;contractCalls&lt;/code&gt; which can be viewed publicly &amp;amp; a public function&lt;code&gt;incrementState&lt;/code&gt; which grabs the address of the user who called the function by using &lt;code&gt;msg.sender&lt;/code&gt; and increments its value in that map.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Note: when grabbing a non-existing &lt;code&gt;msg.sender&lt;/code&gt; address with &lt;code&gt;contractCalls[msg.sender]&lt;/code&gt;, solidity defaults to 0 (zero) for an unsigned int (uint)]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we call &lt;code&gt;contractCalls[msg.sender]&lt;/code&gt; again to see the number accumulated by the user, THAT number, THAT UINT256, IS THE TOKEN!&lt;br&gt;
That's it!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BLQsAVaDJCE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Also, looking at the solidity code, if you've ever worked with any object-oriented language, the &lt;code&gt;contract Test { ... }&lt;/code&gt; syntax along with that &lt;code&gt;public&lt;/code&gt; keyword may look similar to you, because it is. Solidity, like any other OOP language, supports visibility modifiers (&lt;code&gt;public&lt;/code&gt;, &lt;code&gt;private&lt;/code&gt;, &lt;code&gt;internal&lt;/code&gt; &amp;amp; &lt;code&gt;external&lt;/code&gt;) and concepts like inheriting from other contracts.&lt;/p&gt;

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

&lt;p&gt;Yeah, I know, it was an absurd way of telling someone "what is a token?" by teaching them how to write an almost hello world version of a new language, but hey! what if, I would've shown you this instead&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TOKENS are digital assets defined by a project or smart contract and built on a specific blockchain. Token can be UTILITY TOKENS or SECURITY TOKENS. UTILITY TOKENS are also called consumer or incentive tokens&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let us discuss, &lt;strong&gt;&lt;em&gt;"What is an NFT?"&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
NFT, short for Non-Fungible Tokens (which I think, even a 3rd grader knows), is a class of tokens that have a standard protocol of creating, transferring, and burning/destroying them. A smart contract should follow the rules laid down by ERC721 (standard for Non-fungible tokens) in order to even count as an NFT.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;When talking about developing &amp;amp; testing smart contracts, the first thing which comes to me is &lt;a href="https://remix.ethereum.org" rel="noopener noreferrer"&gt;Remix IDE&lt;/a&gt;, an online smart contract compiler. Remix makes writing &amp;amp; testing smart contracts extremely convenient. But Remix is not THE GO-TO choice when developing big projects with solidity.&lt;/p&gt;

&lt;p&gt;To develop complex &amp;amp; big projects in solidity, you need the &lt;strong&gt;Hardhat Toolchain&lt;/strong&gt; which helps you efficiently write smart contracts, compile them, deploy them on testnet or even mainnet and perform automated tests.&lt;/p&gt;

&lt;p&gt;I'll be talking in detail about the whole hardhat dev workflow in another post, as it sometimes makes things LOOK complex while they aren't and in this post, I target to cover our beginner friends too 😉&lt;/p&gt;

&lt;p&gt;For our cute little NFT smart contract, let us, for now, open up the &lt;a href="https://remix.ethereum.org" rel="noopener noreferrer"&gt;Remix IDE&lt;/a&gt;, create a new file in the &lt;code&gt;contracts&lt;/code&gt; folder, and write the following stuff in there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract MyToken is ERC721 {
    uint256 public totalMints = 0;

    uint256 public mintPrice = 1 ether;
    uint256 public maxSupply = 50;
    uint256 public maxPerWallet = 5;
    string public URI = "https://bafybeifqmgyfy4by3gpms5sdv3ft3knccmjsqxfqquuxemohtwfm7y7nwa.ipfs.dweb.link/metadata.json";
    mapping(address =&amp;gt; uint256) public walletMints;

    constructor() ERC721("MyToken", "MTK") {}

    function safeMint(address to) internal {
        uint256 tokenId = totalMints;
        totalMints++;

        _safeMint(to, tokenId);
    }

    function mintToken(uint256 quantity_) public payable {
        require(quantity_ * mintPrice == msg.value, "wrong amount sent");
        require(walletMints[msg.sender] + quantity_ &amp;lt;= maxPerWallet, "mints per wallet exceeded");

        walletMints[msg.sender] += quantity_;
        safeMint(msg.sender);
    }

    function getMyWalletMints() public view returns (uint256) {
        return walletMints[msg.sender];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line is used to tell the solidity compiler &lt;em&gt;what version of solidity we're using&lt;/em&gt;, this is important as &lt;strong&gt;this language is relatively new &amp;amp; thus has ongoing changes&lt;/strong&gt; (and, don't worry, even I don't know what the hell "pragma" means 🤡). And, due to the immutable nature of these smart contracts running on the blockchain, &lt;strong&gt;THERE IS NO UPDATING YOUR CODE&lt;/strong&gt;, thus we need to specify, what version was used when this code was written.&lt;/p&gt;

&lt;p&gt;Next, comes the import statement to import the ERC721 contract from open zeppelin into our contract to add the basic functionality of an NFT on top of our sh*tty code. There are some really important reasons, why we need to import this rather making our own buggy implementation 🐞:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Too lazy to write all of these functions (see implementation docs &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#ERC721" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The implementations provided by open zeppelin are tested hundreds of thousands of times &amp;amp; thus can be trusted more than our own code, also, their code has been optimized to require as low gas fees as possible while providing maximum functionality when run on actual Ethereum nodes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Our contract &lt;code&gt;MyToken&lt;/code&gt; inherits all internal and public variables &amp;amp; functions of the &lt;code&gt;ERC721&lt;/code&gt; contract provided by open zeppelin&lt;/strong&gt;, this means that now we have functions like &lt;code&gt;_safeMint()&lt;/code&gt; that could handle all the functionality of assigning someone a token with some ID, &lt;strong&gt;we just have to control who takes how much &amp;amp; what's the total supply for the NFT.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, in the contract let's define some state variables:&lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;totalMints&lt;/code&gt; is a publicly visible positive integer that we'll be using to count how many tokens have been minted so far. that we'll also use to increment &amp;amp; assign a new &amp;amp; unique number to each token or NFT.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 public totalMints = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mintPrice&lt;/code&gt; is a public uint which has a value of &lt;code&gt;1 ether&lt;/code&gt;, solidity has a special suffix &lt;code&gt;ether&lt;/code&gt; for integers which are to be represented as some ETH value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 public mintPrice = 1 ether;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maxSupply&lt;/code&gt; is the total number of NFTs we decide to mint (public uint) so as to limit mints.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 public maxSupply = 50;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maxPerWallet&lt;/code&gt; is the maximum NFTs a single wallet/user/address can have (public unit).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 public maxPerWallet = 5;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;URI&lt;/code&gt; is the URL which points to JSON data containing &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt; &amp;amp; &lt;code&gt;image&lt;/code&gt; for this NFT. This JSON data is also known as "metadata" &amp;amp; it should at least have at least these 3 properties to correctly show the image in your wallet (Metamask or any other wallet).
Also, I uploaded the JSON metadata file for this NFT on &lt;a href="https://web3.storage" rel="noopener noreferrer"&gt;https://web3.storage&lt;/a&gt; which is a decentralized file system to store &amp;amp; host your uploaded files (see the video below for your "&lt;strong&gt;how to's&lt;/strong&gt;"). You can choose a centralized service or even host it yourself but what's the point of all this if you want to use centralized servers in the end to host the metadata.
Notice when looking at the JSON pasted, I used the image which seems to be coming from a web server &amp;amp; you're correct, which I can justify by saying, "Yeah... 👀" but you would want to host the image on it or any other &lt;a href="https://docs.ipfs.io/concepts/what-is-ipfs/" rel="noopener noreferrer"&gt;IPFS&lt;/a&gt; 😬.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string public URI = "https://bafybeifqmgyfy4by3gpms5sdv3ft3knccmjsqxfqquuxemohtwfm7y7nwa.ipfs.dweb.link/metadata.json";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LlQU9fGfbr8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;walletMints&lt;/code&gt; which is a map datatype to contain key-value pairs of addresses mapped to uint (token ids). We'll be using it to limit mints per wallet.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mapping(address =&amp;gt; string) public walletMints;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now coming to the contract's constructor, a special function that runs only when the contract is deployed. When declaring the constructor, we call the ERC721 contract's constructor to initialize the inherited state from ERC721 with &lt;code&gt;ERC721("TokenName", "TKNSYMBL")&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor() ERC721("MyToken", "MTK") {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice, that after calling ERC721 contract's constructor, we left the body of our contract's constructor empty and that is because, FOR NOW, we don't need to perform any operations when our contract is deployed.&lt;/p&gt;

&lt;p&gt;Next, comes this function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function safeMint(address to) internal {
    uint256 tokenId = totalMints;
    totalMints++;

    _safeMint(to, tokenId);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses the &lt;code&gt;_safeMint&lt;/code&gt; function inherited from the &lt;code&gt;ERC721&lt;/code&gt; contract which mints or assigns an address a token ID. And before doing so, makes sure that the token id is not owned by anyone. There is also a function &lt;code&gt;_mint&lt;/code&gt; that does NOT check for ownership and just assigns the address to the given token id irrespective of whether the token id is already assigned to some address or not (which is almost never recommended... unless you want to shoot yourself in the foot).&lt;/p&gt;

&lt;p&gt;[see a full list of all functions provided by the ERC721 contract &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#ERC721" rel="noopener noreferrer"&gt;here&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Also, while these functions like &lt;code&gt;_safeMint&lt;/code&gt; &amp;amp; &lt;code&gt;_mint&lt;/code&gt; are callable from our inherited contract, users cannot directly call them as &lt;code&gt;internal&lt;/code&gt; functions of a contract are usable by their inherited contract but can't be called from external wallet addresses. If they were callable, anyone could have minted unlimited tokens for free by calling it on their address and different token ids!&lt;/p&gt;

&lt;p&gt;OUR &lt;code&gt;safeMint&lt;/code&gt; function is marked as &lt;code&gt;internal&lt;/code&gt; which means users can't directly call this function externally. This is what we want because the "pay to mint" functionality is still missing from our contract &amp;amp; we will be creating a new function to ensure users follow the rules laid down by us when buying this NFT(e.g following the limits for max supply &amp;amp; mints per wallet).&lt;/p&gt;

&lt;p&gt;To ensure that users are paying for this NFT, we will be creating &lt;em&gt;a function &lt;code&gt;mintToken&lt;/code&gt; which will be calling our &lt;code&gt;internal&lt;/code&gt; function &lt;code&gt;safeMint&lt;/code&gt; along with performing some additional checks&lt;/em&gt;. It'll take a positive integer as its parameter &lt;code&gt;quantity_&lt;/code&gt;, &lt;strong&gt;requiring users to pay the amount of &lt;code&gt;mintPrice * quantity_&lt;/code&gt;&lt;/strong&gt; in ethers (e.g exactly 2 ether for 2 NFT purchases) and check if this purchase does not exceed the &lt;code&gt;maxPerWallet&lt;/code&gt; limit for the wallet calling the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function mintToken(uint256 quantity_) public payable {
    require(quantity_ * mintPrice == msg.value, "wrong amount sent");
    require(walletMints[msg.sender] + quantity_ &amp;lt;= maxPerWallet, "mints per wallet exceeded");

    walletMints[msg.sender] += quantity_;
    safeMint(msg.sender);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;payable&lt;/code&gt; keyword in front of the visibility modifier &lt;code&gt;public&lt;/code&gt; which indicates to the solidity compiler that, specifically this function &lt;code&gt;mintToken&lt;/code&gt; &lt;strong&gt;CAN accept any ether value sent to it while calling it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;"What!? these contracts can store my ether?!" Yup! when someone purchases your NFT, they send this ether to the contract &amp;amp; are stored on the contract itself until you decide to add code to send that balance to yourself, or else the ether is just stuck there FOREVER!&lt;/p&gt;

&lt;p&gt;For checking that the limits are being followed, we use the inbuilt &lt;code&gt;require&lt;/code&gt; function to check a condition, if it turns out to be &lt;code&gt;false&lt;/code&gt;, the function will throw an error with the specified message (in the 2nd argument in the &lt;code&gt;require(condition, "error message")&lt;/code&gt; function), &lt;strong&gt;reverting the whole function call transaction&lt;/strong&gt; along with the sent ether.&lt;/p&gt;

&lt;p&gt;If everything goes fine, it will accept the sent ether, increment the &lt;code&gt;walletMints&lt;/code&gt; for the user's wallet address and call the &lt;code&gt;safeMint&lt;/code&gt; function on the user's address (referenced by &lt;code&gt;msg.sender&lt;/code&gt;) to actually mint the NFT to them.&lt;/p&gt;

&lt;p&gt;The same thing could be done in this way too, where you pass one more parameter in the &lt;code&gt;mintToken&lt;/code&gt; function named &lt;code&gt;recipient&lt;/code&gt; whom to mint the NFT. Both ways are totally right &amp;amp; its your call what to implement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function mintToken(uint256 quantity_, address recipient) public payable {
    require(quantity_ * mintPrice == msg.value, "wrong amount sent");
    require(walletMints[recipient] + quantity_ &amp;lt;= maxPerWallet, "mints per wallet exceeded");

    walletMints[recipient] += quantity_;
    safeMint(recipient);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our NFT contract is almost finished with the functionality to purchase &amp;amp; transfer the tokens, let's test it on remix ide&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zQdd5VvrV7c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Great! now let's write one more function to actually withdraw your "hard-earned" ether from the contract's balance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;address owner;

constructor() ERC721("MyToken", "MTK") {
    owner = msg.sender;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function withdraw() public {
    payable(owner).transfer(address(this).balance);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we declare a variable &lt;code&gt;owner&lt;/code&gt; of a special datatype &lt;code&gt;address&lt;/code&gt; which will store a public wallet address. In the constructor, we assign it to the address of the person who called the constructor, or the person who deployed the contract (by referencing &lt;code&gt;msg.sender&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;withdraw&lt;/code&gt; function is publicly callable &amp;amp; will transfer all the ether balance present in the contract (use &lt;code&gt;address(this).balance&lt;/code&gt; to get the balance of the contract) to the owner's address.&lt;br&gt;&lt;br&gt;
Syntax for sending ETH from contracts to wallet addresses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;payable(sender_address).transfer(X ether)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Aaaand... that's a wrap!&lt;br&gt;
Like this post, if you liked it 🙃&lt;br&gt;&lt;br&gt;
But if you loved it? man you gotta follow me on &lt;a href="https://twitter.com/bhardwajkuvam" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 😉&lt;/p&gt;

&lt;p&gt;Want to show some more love? here's my public wallet address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x9d1092f5cd0459eDaff0bcA6943dC6A6F8F85F38
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to donate 1,2,3,4,5 ETH 😘&lt;/p&gt;




</description>
      <category>web3</category>
      <category>webdev</category>
      <category>blockchain</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I built a Song Recommendation System with Python, Scikit-Learn &amp; Pandas</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Sat, 05 Mar 2022 20:37:08 +0000</pubDate>
      <link>https://dev.to/gohashira/how-i-built-a-song-recommendation-system-with-python-scikit-learn-pandas-11ok</link>
      <guid>https://dev.to/gohashira/how-i-built-a-song-recommendation-system-with-python-scikit-learn-pandas-11ok</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You must've seen Spotify recommending songs to you.&lt;br&gt;
Or other platforms like YouTube &amp;amp; TikTok recommend videos based on your previous viewing experience.&lt;/p&gt;

&lt;p&gt;While building an Indie Project of mine, MeTime🎶  (an ad-free music streaming platform ...coming soon 😉) I wanted to suggest new songs to users &amp;amp; help them discover new sounds. Since then I decided to build a recommendation system that takes in their liked songs &amp;amp; gives out similar tracks or &lt;em&gt;suggests&lt;/em&gt; new songs.&lt;/p&gt;

&lt;p&gt;Here, I'll be talking about how I build it using python and some ML magic with scikit-learn &amp;amp; pandas,&lt;br&gt;
Let's get started!&lt;/p&gt;
&lt;h2&gt;
  
  
  The Dataset
&lt;/h2&gt;

&lt;p&gt;Okay, so now we've taken the quest on, we shall find a dataset that contains some Spotify tracks with their audio features (like danceability, acousticness, energy, positivity... of the song). I believe that &lt;a href="https://kaggle.com" rel="noopener noreferrer"&gt;kaggle&lt;/a&gt; is the best place to hunt data.&lt;br&gt;
Some keyword searches and we can already find so many datasets full of Spotify tracks&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44s989rolid5zw9hq4d7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44s989rolid5zw9hq4d7.png" alt="kaggle search query for Spotify tracks" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On going through the searches, I found &lt;a href="https://www.kaggle.com/saurabhshahane/spotgen-music-dataset/version/122" rel="noopener noreferrer"&gt;this&lt;/a&gt; dataset to be of use&lt;/p&gt;

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

&lt;p&gt;The best thing about this dataset is that it contains every attribute we care about, popularity, energy, danceability, valence (positivity) &amp;amp; instrumentalness. &lt;strong&gt;&lt;em&gt;We'll be using these features to clusterize the dataset into several parts &amp;amp; determine, under what cluster most of the user-favorite tracks lie in&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: You can choose basically any dataset big or small **as long as it has all the necessary audio features&lt;/em&gt;* (popularity, acousticness, energy, valence, danceability &amp;amp; song id) but you should choose as big of a dataset as possible because &lt;strong&gt;bigger data sets generally mean a large number of data points which offers us a good stand to recommend songs &amp;amp; train our ML models&lt;/strong&gt;*&lt;/p&gt;

&lt;p&gt;Let's now open up a jupyter notebook and import the downloaded dataset with pandas&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1of2jrejp27t2heyw7ln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1of2jrejp27t2heyw7ln.png" alt="jupyter notebook in vscode &amp;amp; dataset import" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  "What just happened?"
&lt;/h4&gt;

&lt;p&gt;Here, we used pandas &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pandas is a python library to read, write, manipulate, visualize &amp;amp; query data) to read the dataset from the csv file&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;...and load it in a pandas data frame.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data frames in Pandas provide us the right functions or methods to perform the appropriate operations on the given data&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Clusterizing the Dataset
&lt;/h2&gt;

&lt;p&gt;Now the question arises &lt;strong&gt;"How are we going to clusterize the dataset based on the tracks' audio features?"&lt;/strong&gt;, here comes scikit-learn into the play, &lt;strong&gt;sklearn has many utility import-and-use mathematical models which make things a lot easier when &lt;em&gt;handling data &amp;amp; performing statistical functions&lt;/em&gt;&lt;/strong&gt; on it. But before we even use sklearn or scikit-learn, it's a natural tendency for newbies to ask &lt;strong&gt;"What the heck is that?"&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SciKit-Learn is a python library that contains various readily usable modules that help in analyzing, predicting &amp;amp; visualizing data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sklearn has a module called &lt;code&gt;clusters&lt;/code&gt; which contains the &lt;code&gt;KMeans&lt;/code&gt; model, that helps us do exactly the thing we require... divide data into certain groups. (you can have more info on how the &lt;code&gt;KMeans&lt;/code&gt; algorithm works &lt;a href="https://www.youtube.com/watch?v=R2e3Ls9H_fc" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Generally speaking, before performing any statistical operation on data, it's a good practice to first have a look at the correlations among its features &amp;amp; plot graphs between them so that we could get an idea &amp;amp; visualize any natural patterns developing within it. For that, we use our friend &lt;code&gt;pandas&lt;/code&gt; to plot a graph between all features correlating all of them with every one of them.&lt;/p&gt;

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

&lt;p&gt;In the 3rd code block of the notebook, all I did was reduce this big 'ol dataset to 1000 data points or "sliced" it (similar to slicing a list), picked out only the columns or features I want to plot the graph of (you can pick specific columns of a pandas data frame with this syntax) and passed it to the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pd.plotting.scatter_matrix(frame, figsize=( , ))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason why I reduced was if I were to perform the &lt;code&gt;scatter_matrix&lt;/code&gt; operation on the whole dataset, it would have taken 5-7 minutes to process all the hundreds &amp;amp; thousands of tracks in the data frame &amp;amp; plot their features graphically.&lt;br&gt;
Also, I used the &lt;code&gt;figsize&lt;/code&gt; param to scale the graph providing width &amp;amp; height in a Python tuple (so that I could get the plot in 1 screenshot 😅).&lt;/p&gt;

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

&lt;p&gt;Having looked at plots, we can see quite good correlations between features like danceability, valence &amp;amp; energy. To confirm this, let us draw a numerical table to see the correlations in numbers with &lt;code&gt;pandas&lt;/code&gt; built-in methods&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmga1dcj359bc1cupz655.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmga1dcj359bc1cupz655.png" alt="correlations method in pandas dataframe" width="725" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, coming to our specific case where we would be wanting to create groups in the data, seeing the correlations visually &amp;amp; numerically, no apparent natural groups are forming in this data. Thus, we will be testing out &amp;amp; tinkering a little bit with how many clusters we want to create, too low and we end up categorizing multiple genres in 1 cluster, too high and we lose tracks of the same genres in a cluster.&lt;/p&gt;

&lt;p&gt;Let's see how we can do this in Python syntax...&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zx22q94au4uts7ed2lo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zx22q94au4uts7ed2lo.png" alt="python code to categorize tracks" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, I picked up the main features which heavily impact what type of song it is, hence impacting what cluster it belongs to &amp;amp; stored the new data frame in the &lt;code&gt;tracks&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Then, I initialized the &lt;code&gt;KMeans&lt;/code&gt; model &amp;amp; stored it in the corresponding variable, after that, I "fitted" or "trained" the model on the data using the &lt;code&gt;.fit()&lt;/code&gt; method and passed in the data we want the model to "train" on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By "training" or "fitting" I mean that the &lt;code&gt;KMeans&lt;/code&gt; model will determine in what cluster each track with its particular audio features SHOULD lie in &amp;amp; assign cluster numbers to it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After fitting the data set, it will store the cluster numbers (which will be a list of positive integers ranging from 0 to 4 in this case) in a variable called &lt;code&gt;labels_&lt;/code&gt; arranged in a way that corresponds to each track in the data frame.&lt;/p&gt;
&lt;h2&gt;
  
  
  Giving out recommendations
&lt;/h2&gt;

&lt;p&gt;Now, coming to the last act of our quest, what we're going to do is, Edit &amp;amp; save the above generated &lt;code&gt;labels_&lt;/code&gt; in a column for each track, save the dataset in a separate csv file and &lt;strong&gt;find out what cluster number occurs the most in a user's playlist thus finding out what type of songs user likes the most &amp;amp; giving them tracks with same cluster number&lt;/strong&gt; or you could say of same "type"&lt;/p&gt;

&lt;p&gt;In pandas, we add a column to a data frame with the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dataframe[column_name] = an_array_with_same_number_of_rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhadexzxb0lmszck9igev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhadexzxb0lmszck9igev.png" alt="pandas data frame with new column - type" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding, its time to save the newly altered data frame in a csv file by using the &lt;code&gt;.to_csv()&lt;/code&gt; method of our convenient pandas data frame&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tracks_df.to_csv('../result.csv')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now create a Python program that would take in the IDs of user favorite tracks and suggest 'em some nice songs!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# CONSTRUCT YOUR OWN LOGIC!
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./result.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Enter comma-separated ids of your favorite songs&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# sample input: 1xK1Gg9SxG8fy2Ya373oqb,1xQ6trAsedVPCdbtDAmk0c,7ytR5pFWmSjzHJIeQkgog4,079Ey5uxL04AKPQgVQwx5h,0lizgQ7Qw35od7CYaoMBZb,7r9ZhitdQBONTFOiJW5mr8,3ee8Jmje8o58CHK66QrVC2,3ZG8N7aWw2meb6UrI5ZmnZ,5cpJFiNwYyWwFLH0V6B3N8,26w9NTiE9NGjW1ZvIOd1So,7BIy3EGQhg98CsRdKYHnJC,2374M0fQpWi3dLnB54qaLX,2IVsRhKrx8hlQBOWy4qebo,40riOy7x9W7GXjyGp4pjAv,4evmHXcjt3bTUHD1cvny97,0MF5QHFzTUM2dYm6J7Vngt,0TrPqhAMoaKUFLR7iYDokf,07KXEDMj78x68D884wgVEm,6gxKUmycQX7uyMwJcweFjp
&lt;/span&gt;
&lt;span class="c1"&gt;# search the specified ids in this dataset and get the tracks
&lt;/span&gt;&lt;span class="n"&gt;favorites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;# code to sort find out the maximum occuring cluster number according to user's favorite track types
&lt;/span&gt;&lt;span class="n"&gt;cluster_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;favorites&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;clusters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cluster_numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;clusters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cluster_numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# sort the cluster numbers and find out the number which occurs the most
&lt;/span&gt;&lt;span class="n"&gt;user_favorite_cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clusters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])][&lt;/span&gt;&lt;span class="mi"&gt;0&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Favorite cluster:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_favorite_cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# finally get the tracks of that cluster
&lt;/span&gt;&lt;span class="n"&gt;suggestions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;user_favorite_cluster&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# now print the first 5 rows of the data frame having that cluster number as their type
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suggestions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To the above code, you would want to do some improvisations and I knowingly left room for some, but there's one big problem about the above mechanism, It will recommend non-hits from the 1950s or 1960s too and I think no one would be willing to hear them over a popular song like "Despacito" (still love that song), so it would be a good move to filter out songs according to popularity say &amp;gt; 60 or 70 the moment we read the dataset. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
tracks = tracks[tracks.popularity &amp;gt; 70]
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And... that was it! this was the bare minimum code to suggest similar tracks to users. You can now host a full-fledged flask server for just providing recommendations taking in the liked track ids from the user or make a CLI tool for devs to discover new songs from Spotify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrate Spotify API &amp;amp; away you go!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv124qk09a28qriskqvyk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv124qk09a28qriskqvyk.gif" width="500" height="500"&gt;&lt;/a&gt;&lt;br&gt;
Meet you another day with another post ;)&lt;/p&gt;




&lt;p&gt;I hope you liked this post, Any feedback is much appreciated!&lt;br&gt;
If you like my posts, consider following :)&lt;/p&gt;

&lt;p&gt;Twitter -&amp;gt; &lt;a href="https://twitter.com/BhardwajKuvam" rel="noopener noreferrer"&gt;@BhardwajKuvam&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Github -&amp;gt; &lt;a href="https://github.com/kuvamdazeus" rel="noopener noreferrer"&gt;@kuvamdazeus&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn -&amp;gt; &lt;a href="https://www.linkedin.com/in/kuvambhardwaj" rel="noopener noreferrer"&gt;@kuvambhardwaj&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Portfolio -&amp;gt; &lt;a href="https://kuvambhardwaj.vercel.app" rel="noopener noreferrer"&gt;kuvambhardwaj.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/kuvam" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lokbm1o1fdnkevsvr7m.png" width="453" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>programming</category>
    </item>
    <item>
      <title>Adding Dynamic Search Auto-Complete to a web application with NodeJS and React 🔍</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Wed, 09 Feb 2022 18:18:04 +0000</pubDate>
      <link>https://dev.to/gohashira/adding-dynamic-search-auto-complete-to-a-web-application-with-nodejs-and-react-2lh4</link>
      <guid>https://dev.to/gohashira/adding-dynamic-search-auto-complete-to-a-web-application-with-nodejs-and-react-2lh4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You must've seen google's autocomplete search bar predict your next keystrokes as you type in it&lt;/p&gt;

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

&lt;p&gt;So, I thought of building one and sharing my findings with y'all.&lt;br&gt;
Let's get started 🚀&lt;/p&gt;
&lt;h2&gt;
  
  
  Google's search auto-complete API
&lt;/h2&gt;

&lt;p&gt;I was making an app that required me to implement this sort of thing where a user starts typing and some search suggestions would come flying in his face (in a div of course). So I started to wander around on google for some free APIs. In the quest, I stumbled upon &lt;a href="https://stackoverflow.com/questions/6428502/google-search-autocomplete-api" rel="noopener noreferrer"&gt;this&lt;/a&gt; stack overflow discussion. One of the answers suggested to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://www.google.com/complete/search?client=hp&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;hl=en&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;sugexp=msedr&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;gs_rn=62&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;gs_ri=hp&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;cp=1&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;gs_id=9c&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;q=a&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;xhr=t&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;callback=hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This basically is the URL that google.com itself uses for its search suggestions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1uyhvbcpwoafodl1udi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1uyhvbcpwoafodl1udi.png" alt="google.com search suggestions page with inspector opened at network tab" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  API Endpoint
&lt;/h2&gt;

&lt;p&gt;Let's now get on writing some GET requests to google's API from a test browser environment, I find codesandbox.io the best way to set up a quick hosted web environment for such things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgb16lljv0ygmhowlw3ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgb16lljv0ygmhowlw3ds.png" alt="code sandbox code to fetch google auto-complete search API" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And.....refresh!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcil1d9x0iv7ui903sqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcil1d9x0iv7ui903sqa.png" alt="access control origin error from browser environment" width="588" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hmm, so this is a CORS error, relatively easy to fix only if you know how to work with NodeJS ;)&lt;/p&gt;

&lt;h3&gt;
  
  
  "What just happened?"
&lt;/h3&gt;

&lt;p&gt;These errors happen when a header &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; is not present. Responses from requests that don't have this header are blocked by the browser even if the request returns 200 OK.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Access-Control-Allow-Origin response header indicates whether the response can be shared with requesting code from the given origin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Find more on this header &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin" rel="noopener noreferrer"&gt;here&lt;/a&gt;. This error is only raised in a browser environment. Therefore, now we will be switching this request-making code block to a node environment and then return the response to the requesting client for our node API endpoint.&lt;/p&gt;

&lt;p&gt;Also, if we just make a GET request with our local machine, like on postman or insomnia. It will be returning a normal response for our specified url-encoded query &lt;code&gt;q&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcttdd2bjac0k42ahtvie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcttdd2bjac0k42ahtvie.png" alt="200 OK insomnia response for google auto-complete search api" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's code our node endpoint to get the search suggestions and return them as a JSON response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo2x2jmbhtlmu4ojxe4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo2x2jmbhtlmu4ojxe4a.png" alt="replit nodejs app to fetch and return autocomplete search results as json" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For quick code snippets instantly deployed in a hosted environment, I often like to use replit.com.&lt;br&gt;
In this code, I imported &lt;code&gt;express&lt;/code&gt; (for spinning up a web server) and &lt;code&gt;axios&lt;/code&gt; (for making GET/POST requests to sources over the internet).&lt;/p&gt;

&lt;p&gt;Then, I initialized the express server/app and defined an API GET ENDPOINT with the &lt;code&gt;.get(url, (request, response) =&amp;gt; {})&lt;/code&gt; method, made a GET request with &lt;code&gt;axios&lt;/code&gt; to google's API and sent the returned suggestions data to the requesting client.&lt;/p&gt;

&lt;p&gt;Testing the newly made endpoint, will obviously return a 200 OK response and provide us with the search results&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mjvrv2ijckolfzb8cy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mjvrv2ijckolfzb8cy2.png" alt="I am the best in nodejs" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;But there is 1 more task remaining with our endpoint, returning nice &amp;amp; sweetly formatted search suggestions in the JSON format&lt;/p&gt;

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

&lt;p&gt;For this part of the code, I referenced the main part of the result with some indexing, used regular expressions to grab just the part where it gives the actual completion text, and add some null checks for the regex matches. Now our API response looks something like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frml4sie1n54v953l5ml6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frml4sie1n54v953l5ml6.png" alt="nice and sweet response" width="747" height="304"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing the API in a React application
&lt;/h2&gt;

&lt;p&gt;So, now comes the part where we actually use our API to dynamically suggest users for their search keystrokes. On code sandbox, let's spin up a basic react app that takes input &amp;amp; saves it in its state&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7rood8dtwcw0lo44xy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7rood8dtwcw0lo44xy7.png" alt="basic react app with simple input state" width="588" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we don't want to spam our endpoint with dozens of requests on every keystroke whenever the input value is changed. So, we'll be implementing a timeout-based request fetching, something 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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;searchResults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSearchResults&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInputText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputTimer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInputTimer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInputChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setInputText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputTimer&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;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCHING RESULTS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;axios&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s2"&gt;`https://autocomplete-google-search.kuvambhardwaj.repl.co/autocomplete?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setInputTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInputChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Type something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30px&lt;/span&gt;&lt;span class="dl"&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;ul&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;searchResults&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;searchResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&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;searchResult&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;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="p"&gt;))}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/center&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now what we're doing is set a timeout for like 300ms whenever the input value changes &amp;amp; store the timeout reference in the state, if the user enters a letter and the input value is changed within 300ms, it will clear the previously set timeout and initialize a new one. After 300ms of input inactivity, we will be finally making autocomplete request with the most recent value of the input.&lt;br&gt;
The application should work something like this&lt;/p&gt;

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

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




&lt;p&gt;If you like my posts, consider following :)&lt;/p&gt;

&lt;p&gt;Twitter -&amp;gt; &lt;a href="https://twitter.com/BhardwajKuvam" rel="noopener noreferrer"&gt;@BhardwajKuvam&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Github -&amp;gt; &lt;a href="https://github.com/kuvamdazeus" rel="noopener noreferrer"&gt;@kuvamdazeus&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn -&amp;gt; &lt;a href="https://www.linkedin.com/in/kuvambhardwaj" rel="noopener noreferrer"&gt;@kuvambhardwaj&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Portfolio -&amp;gt; &lt;a href="https://kuvambhardwaj.vercel.app" rel="noopener noreferrer"&gt;kuvambhardwaj.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/kuvam" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lokbm1o1fdnkevsvr7m.png" width="453" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>node</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating Custom Hooks with React.js</title>
      <dc:creator>gohashira</dc:creator>
      <pubDate>Wed, 15 Dec 2021 12:21:50 +0000</pubDate>
      <link>https://dev.to/gohashira/creating-custom-hooks-with-reactjs-50j6</link>
      <guid>https://dev.to/gohashira/creating-custom-hooks-with-reactjs-50j6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hooks were introduced quite a while ago in React. They enabled to tap into state &amp;amp; lifecycle methods WITHOUT using class components.&lt;/p&gt;

&lt;p&gt;In this post I will be showing you with the help of a common problem, how can you create a hook for your own. Let's Get Started 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;So let's suppose we're making a web app where we need to render different components depending upon the &lt;em&gt;screen width&lt;/em&gt; of the user.&lt;/p&gt;

&lt;p&gt;So we wrote this code to solve it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugqbqme9clc0rlf7fhhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugqbqme9clc0rlf7fhhu.png" alt="arbitrary code to solve window screen width problem" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will work fine. Missing one crucial case, &lt;strong&gt;What if the user switches to landscape mode on its mobile?&lt;/strong&gt; The site will still be showing the mobile screen component &lt;em&gt;instead of showing the desktop or bigger screen component&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Of course, this problem can be solved with CSS &amp;amp; rather with 2-3 words with tailwind.&lt;br&gt;
The thing is, I want to show you another way of solving this problem &lt;strong&gt;The Reactive&lt;/strong&gt; way!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Hook Component
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  What just happened?
&lt;/h3&gt;

&lt;p&gt;Here, if you look at the &lt;code&gt;useWindowWidth&lt;/code&gt; function, you'll notice that it's just a normal function that also happens to use other built-in hooks like &lt;code&gt;useState&lt;/code&gt; &amp;amp; &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What this function does is, it declares a state variable &lt;em&gt;in its scope&lt;/em&gt; with &lt;code&gt;useState&lt;/code&gt; calling it &lt;code&gt;width&lt;/code&gt; &amp;amp; its setter &lt;code&gt;setWidth&lt;/code&gt; and throws in the value of &lt;code&gt;window.screen.width&lt;/code&gt; as its initial state.&lt;/p&gt;

&lt;p&gt;Then, we call the &lt;code&gt;useEffect&lt;/code&gt; hook and add an event listener for the 'resize' event firing off a function that sets the value of &lt;code&gt;width&lt;/code&gt; whenever the browser window is resized.&lt;/p&gt;

&lt;p&gt;If you look closely at the &lt;code&gt;useEffect&lt;/code&gt; hook, you'll see an empty array which is there to indicate that &lt;em&gt;this &lt;code&gt;useEffect&lt;/code&gt; does not depend on any external value&lt;/em&gt; meaning that it will ONLY RUN ONCE even in occasional re-renders. &lt;strong&gt;This array is also called the DEPENDENCY ARRAY of the &lt;code&gt;useEffect&lt;/code&gt; hook&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next, we return the &lt;code&gt;width&lt;/code&gt; value as the output of this function. Next time the browser window is resized, it will return a new value of &lt;code&gt;width&lt;/code&gt; representing the window's current screen width. And we know that whenever we associate &lt;code&gt;useState&lt;/code&gt; to a variable, &lt;em&gt;it causes a re-render in every location where the variable was referenced&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is how it is working now:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwb7awwiolfcz2sj5lhe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwb7awwiolfcz2sj5lhe.gif" alt="working of custom hooks" width="480" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those of you thinking:&lt;br&gt;&lt;br&gt;
" Hey! but why we prefixed 'use' with the function's name in &lt;code&gt;useWindowWidth&lt;/code&gt;? "&lt;/p&gt;

&lt;p&gt;This is a text I extracted from the &lt;a href="https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; of React.js on custom hooks, have a look:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do I have to name my custom Hooks starting with “use”? Please do. This convention is very important. Without it, we wouldn’t be able to automatically check for violations of rules of Hooks because we couldn’t tell if a certain function contains calls to Hooks inside of it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;The use of custom hooks is not limited to just this use case, you can apply it pretty much anywhere you like from auto-login functions to UI-related parts. Even making queries to the server on regular basis, that helps deliver a near-real-time experience to the end user. Possibilities are, as always, ENDLESS.&lt;/p&gt;

&lt;p&gt;So, that's all for today folks! hope you found it helpful :)&lt;/p&gt;




&lt;p&gt;If you like my posts, consider following :)&lt;/p&gt;

&lt;p&gt;Twitter -&amp;gt; &lt;a href="https://twitter.com/BhardwajKuvam" rel="noopener noreferrer"&gt;@BhardwajKuvam&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Github -&amp;gt; &lt;a href="https://github.com/kuvamdazeus" rel="noopener noreferrer"&gt;@kuvamdazeus&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn -&amp;gt; &lt;a href="https://www.linkedin.com/in/kuvambhardwaj" rel="noopener noreferrer"&gt;@kuvambhardwaj&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Portfolio -&amp;gt; &lt;a href="https://kuvambhardwaj.vercel.app" rel="noopener noreferrer"&gt;kuvambhardwaj.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/kuvam" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lokbm1o1fdnkevsvr7m.png" width="453" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
