<?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: Sunny Singh</title>
    <description>The latest articles on DEV Community by Sunny Singh (@sunnysingh).</description>
    <link>https://dev.to/sunnysingh</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%2F14721%2F90a9a8b4-ce8b-4513-ab5b-2514e9f5aed3.jpg</url>
      <title>DEV Community: Sunny Singh</title>
      <link>https://dev.to/sunnysingh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sunnysingh"/>
    <language>en</language>
    <item>
      <title>VS Code Quick Tip: JavaScript Import Autocomplete</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Wed, 11 Nov 2020 20:26:03 +0000</pubDate>
      <link>https://dev.to/sunnysingh/vs-code-quick-tip-javascript-import-autocomplete-gk6</link>
      <guid>https://dev.to/sunnysingh/vs-code-quick-tip-javascript-import-autocomplete-gk6</guid>
      <description>&lt;p&gt;&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; (VS Code) is an extremely popular code editor that is mainly used for frontend web development. One of its features is a sophisticated code completion system known as &lt;a href="https://code.visualstudio.com/docs/editor/intellisense"&gt;IntelliSense&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;IntelliSense works well... except with JavaScript module imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s1"&gt;react&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;If you start to type &lt;code&gt;import&lt;/code&gt; you have to decide &lt;em&gt;what&lt;/em&gt; you are importing first, instead of &lt;em&gt;where&lt;/em&gt; you are importing from. This unfortunately causes an issue for VS Code because it has no idea what to suggest for available imports.&lt;/p&gt;

&lt;p&gt;Let's compare this syntax to other languages such as Python:&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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since you start the statement with &lt;code&gt;from math&lt;/code&gt;, it is easier for the editor to give you suggestions on what is available for you to import from the module.&lt;/p&gt;

&lt;p&gt;Okay, this is great news for Python, but what about our beloved JavaScript and Node.js code? Don't worry! I came across a fantastic solution for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Solution: Fake reverse the import statement
&lt;/h2&gt;

&lt;p&gt;If I could go back in time and make JavaScript's import syntax work like Python's, I would. However, we can work with what we got by trying to fake reverse the import.&lt;/p&gt;

&lt;p&gt;You do this by simply typing &lt;code&gt;import&lt;/code&gt; and waiting for a menu to pop up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PVW8G27Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mridye82hqj0ku7au7yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVW8G27Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mridye82hqj0ku7au7yo.png" alt="VS Code's suggestion menu after typing import"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to select the &lt;code&gt;import statement&lt;/code&gt; option by using the arrow keys and then pressing the &lt;code&gt;Enter&lt;/code&gt; key. You should then see a template for an import statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&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;The &lt;code&gt;module&lt;/code&gt; text will be highlighted and selected, so you can start typing &lt;em&gt;where&lt;/em&gt; to import from first. After that, press the &lt;code&gt;Tab&lt;/code&gt; key and the cursor will move in between the curly braces. Now, you can type &lt;em&gt;what&lt;/em&gt; you want to import and VS Code will be able to offer you suggestions.&lt;/p&gt;




&lt;p&gt;Did you find this tip useful? Have your own tip to share? I would love to know, so &lt;a href="https://twitter.com/sunnysinghio"&gt;reach out on Twitter&lt;/a&gt; or leave a comment.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Quick tip: Manage Node versions for your projects</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Thu, 05 Nov 2020 14:22:53 +0000</pubDate>
      <link>https://dev.to/sunnysingh/quick-tip-manage-node-versions-for-your-projects-1d2d</link>
      <guid>https://dev.to/sunnysingh/quick-tip-manage-node-versions-for-your-projects-1d2d</guid>
      <description>&lt;p&gt;When I start a new project, I am likely going to run &lt;a href="https://docs.npmjs.com/cli/init/"&gt;&lt;code&gt;npm init&lt;/code&gt;&lt;/a&gt;. It can be a backend API, a frontend application, or a simple static site.&lt;/p&gt;

&lt;p&gt;This means that &lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt; is powering all of my projects and it's unlikely that I am able to keep all of them working with the same Node version. For example, I may have a legacy project that uses Node v8 while a newer project uses Node v14.&lt;/p&gt;

&lt;p&gt;A tool to help with this problem exists and you may already be aware of it: &lt;a href="https://github.com/nvm-sh/nvm"&gt;Node Version Manager (NVM)&lt;/a&gt;. It allows you to install and use different versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install and use Node v14&lt;/span&gt;
nvm &lt;span class="nb"&gt;install &lt;/span&gt;14
nvm use 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this manual process can be tedious when switching between projects. Imagine opening a project and instinctly trying to run &lt;code&gt;npm start&lt;/code&gt;. Uh oh, you see some errors. You begin debugging until realizing that you're on a wrong Node.js version! You then have to remember the right version or look at the readme.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Solution: the &lt;code&gt;.nvmrc&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;Did you know that &lt;a href="https://github.com/nvm-sh/nvm"&gt;NVM&lt;/a&gt; can automatically detect which version to use in a project? You can enable this by adding a &lt;a href="https://github.com/nvm-sh/nvm#nvmrc"&gt;&lt;code&gt;.nvmrc&lt;/code&gt; file&lt;/a&gt; which should contain a Node version:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;nvm use&lt;/code&gt; in the project and NVM will figure out to install and use &lt;code&gt;14.15.0&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;: You can even have your shell automatically run &lt;code&gt;nvm use&lt;/code&gt; when it detects an &lt;code&gt;.nvmrc&lt;/code&gt; file! &lt;a href="https://github.com/nvm-sh/nvm#deeper-shell-integration"&gt;Read the NVM docs&lt;/a&gt; to learn how to set it up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🏎 Honorable mention: the &lt;code&gt;engines&lt;/code&gt; field
&lt;/h2&gt;

&lt;p&gt;NVM obviously uses the &lt;code&gt;.nvmrc&lt;/code&gt; file, but some other tools and services may as well. Notably, &lt;a href="https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript"&gt;Netlify uses nvmrc&lt;/a&gt; to detect which Node.js version to build your site with.&lt;/p&gt;

&lt;p&gt;However, other services &lt;a href="https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"&gt;such as Heroku&lt;/a&gt; use the &lt;a href="https://docs.npmjs.com/cli/v6/configuring-npm/package-json#engines"&gt;engines field in package.json&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-package"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=14.15.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=6.14.8"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This field actually matters significantly when it comes to publishing packages to NPM with version requirements, and also has the added benefit of being able to specify the version of the package manager (NPM or Yarn) as well.&lt;/p&gt;




&lt;p&gt;Maintaining different Node.js versions is now a problem of the past. Did you like this quick tip? Maybe you have one to suggest? Leave a comment or send me &lt;a href="https://twitter.com/sunnysinghio"&gt;a tweet&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I added realtime search to my static site</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Tue, 03 Nov 2020 17:21:02 +0000</pubDate>
      <link>https://dev.to/sunnysingh/how-i-added-realtime-search-to-my-static-site-lg0</link>
      <guid>https://dev.to/sunnysingh/how-i-added-realtime-search-to-my-static-site-lg0</guid>
      <description>&lt;p&gt;One of the side projects that I run is &lt;a href="https://resrc.dev/"&gt;Resrc&lt;/a&gt;, a site where I curate useful or interesting resources for software development.&lt;/p&gt;

&lt;p&gt;Since the site is typically updated once a day and does not offer complex dynamic features, I decided to go with a static site architecture also known as &lt;a href="https://jamstack.org/"&gt;Jamstack&lt;/a&gt;. The actual tech stack that I went with is &lt;a href="https://airtable.com/"&gt;Airtable&lt;/a&gt; for the database and &lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt; for the static site generator. This works extremely well because of Gatsby's data source plugin system to allow pulling in data from Airtable at build time with ease.&lt;/p&gt;

&lt;p&gt;However, people tend to question this architecture...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I add a dynamic feature, such as search, to a static site?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is possible, but requires a different set of tools than what you might traditionally be used to. In my case, I already used those tools: Airtable and Netlify.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Storing and querying data with &lt;a href="https://airtable.com/"&gt;Airtable&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://airtable.com/"&gt;Airtable&lt;/a&gt; is a service that looks like a spreadsheet but behaves like a database.&lt;/p&gt;

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

&lt;p&gt;The best part is you get access to a full API:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QgnxjJ2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6egcg98f0ckhw7w1lkgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QgnxjJ2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6egcg98f0ckhw7w1lkgp.png" alt="Airtable API documentation for Resrc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The API has advanced filtering capabilities which allows performing a full text search on various fields of my data, realtime. I got really excited because I thought: now I just build out a search UI, send an ajax request to fetch results, and I'm done!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hmm, not quite.&lt;/em&gt; Airtable currently does not have access control features, meaning that if I exposed my API key on the frontend then anyone could submit a request to delete my data. That is not exactly what I would call secure.&lt;/p&gt;

&lt;p&gt;Note that this article intends to be a tutorial, so to continue on I recommend that you &lt;a href="https://support.airtable.com/hc/en-us/articles/202578749-Creating-a-new-empty-base"&gt;create an Airtable base&lt;/a&gt;, &lt;a href="https://support.airtable.com/hc/en-us/articles/216108577-Adding-a-new-record#:~:text=You%20can%20add%20a%20new,%2Fbelow%22%20from%20the%20menu."&gt;add some records&lt;/a&gt;, and then &lt;a href="https://airtable.com/api"&gt;check out the API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Securing the API key with &lt;a href="https://www.netlify.com/products/functions/"&gt;Netlify Functions&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; is a service that handles deploys for static sites. Amongst many features that are useful for static sites, they offer serverless functions. While &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS Lambda&lt;/a&gt; is used under the hood, you don't have to worry about complex implementation details.&lt;/p&gt;

&lt;p&gt;The reason that we'd want to use serverless functions is because they provide a way of proxying our requests to the Airtable API, thus hiding our API key. Instead of the frontend making direct requests to Airtable, it is made to the serverless function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This tutorial assumes that you already created a site with a static site generator such as &lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt;, &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; or &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To set up Netlify Functions, we first need to create a &lt;code&gt;netlify.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
  &lt;span class="py"&gt;functions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"functions"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also store our API key in a &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AIRTABLE_API_KEY=PLACEHOLDER
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that &lt;code&gt;.env&lt;/code&gt; files are &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/using-git/ignoring-files"&gt;ignored by Git&lt;/a&gt; and thus never committed to your repository. You will also have to add this key as an &lt;a href="https://docs.netlify.com/configure-builds/environment-variables/"&gt;environment variable in Netlify&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, create the file &lt;code&gt;functions/search.js&lt;/code&gt;:&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;Airtable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;airtable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AIRTABLE_API_KEY&lt;/span&gt; &lt;span class="o"&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;AIRTABLE_API_KEY&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;AIRTABLE_BASE_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PLACEHOLDER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// TODO: Replace placeholder.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AIRTABLE_TABLE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PLACEHOLDER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// TODO: Replace placeholder.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AIRTABLE_PAGE_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&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;RESPONSE_HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;query&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryStringParameters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;query&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query is required.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;AIRTABLE_API_KEY&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Airtable API key is missing.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Airtable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AIRTABLE_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;AIRTABLE_BASE_ID&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;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AIRTABLE_TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AIRTABLE_PAGE_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO: Update to use your field names.&lt;/span&gt;
      &lt;span class="na"&gt;filterByFormula&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
      OR(
        SEARCH("&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;", LOWER({Name})),
        SEARCH("&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;", LOWER({Description})),
        SEARCH("&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;", LOWER({Category})),
        SEARCH("&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;", LOWER({URL}))
      )
    `&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;firstPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Search error from Airtable API: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noResults&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No results.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RESPONSE_HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;results&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;Make sure to replace the &lt;code&gt;// TODO&lt;/code&gt; comments with your own keys and fields.&lt;/p&gt;

&lt;p&gt;Let's now install the &lt;a href="https://github.com/Airtable/airtable.js"&gt;Airtable JavaScript client&lt;/a&gt; and &lt;a href="https://docs.netlify.com/cli/get-started/"&gt;Netlify CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;airtable
npm &lt;span class="nb"&gt;install &lt;/span&gt;netlify-cli &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And connect our Netlify account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx netlify login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can launch our development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx netlify &lt;span class="nt"&gt;--command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"npm run develop"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;npm run develop&lt;/code&gt; with the command you normally use to start your server.&lt;/p&gt;

&lt;p&gt;Our search results can now be accessed at the following search endpoint: &lt;a href="http://localhost:8888/.netlify/functions/search?query=test"&gt;http://localhost:8888/.netlify/functions/search?query=test&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚛️ Fetching data efficiently with &lt;a href="https://react-query.tanstack.com/"&gt;React Query&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://react-query.tanstack.com/"&gt;React Query&lt;/a&gt; is an amazing data fetching library but is optional because you can go ahead and create your frontend however you'd like. For example, you could create an HTML form and send a request to the search endpoint using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;Fetch API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, I put React Query in the title of this article so I am obligated to share how I implemented a more efficient fetching strategy for Resrc. Let's jump into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔎 The Search component
&lt;/h3&gt;

&lt;p&gt;The component should provide a standard form with state management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="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="nx"&gt;Search&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/search?query=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;query&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&lt;/span&gt;
        &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Search query"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Resrc, I have the search form displayed in the header. This is why I made the decision to navigate to a &lt;code&gt;/search&lt;/code&gt; route whenever the form is submitted. This...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows sharing the search results page URL.&lt;/li&gt;
&lt;li&gt;Simplifies data fetching to be on page load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also note that in a single page app you should use a client side route navigation instead. Gatsby provides a &lt;a href="https://www.gatsbyjs.com/docs/gatsby-link/#how-to-use-the-navigate-helper-function"&gt;navigate helper&lt;/a&gt; and Next.js provides a &lt;a href="https://nextjs.org/docs/api-reference/next/router#userouter"&gt;useRouter hook&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚓️ The useSearch hook
&lt;/h3&gt;

&lt;p&gt;Okay, now let's fetch some data! Create a search page and component in your site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SEARCH_API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/.netlify/functions/search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchSearch&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Search query is required.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetch&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="nx"&gt;SEARCH_API_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?query=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;fetchSearch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;SearchResultsPage&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No results&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how we abstracted the data fetching into a custom hook called &lt;code&gt;useSearch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that, the search functionality is now finished:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Type &lt;code&gt;test&lt;/code&gt; into the search form and press Enter.&lt;/li&gt;
&lt;li&gt; Page is navigated to &lt;code&gt;/search?query=test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; React Query fetches results from &lt;code&gt;/.netlify/functions/search?query=test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Results are rendered depending on loading, success, or error status.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that I didn't provide any design here so it's up to you to decide how best to display the data. However, you can quickly spruce up the experience by implement a ready made design component system such as &lt;a href="https://chakra-ui.com/"&gt;Chakra UI&lt;/a&gt;. I use it for Resrc.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎁 Wrapping up
&lt;/h2&gt;

&lt;p&gt;Let's quickly recap the different layers of our realtime search stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Airtable provides a full text search API to query the data we have stored.&lt;/li&gt;
&lt;li&gt;Netlify Functions proxies our API requests to Airtable and hides the API key.&lt;/li&gt;
&lt;li&gt;React Query fetches search results with some added features such as caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you get stuck, feel free to reference the &lt;a href="https://github.com/sunnysingh/resrc.dev"&gt;source code of Resrc on GitHub&lt;/a&gt;. You are also always free to send me &lt;a href="https://sunnysingh.io/contact"&gt;an email&lt;/a&gt; or &lt;a href="https://twitter.com/sunnysinghio"&gt;or a tweet&lt;/a&gt; with questions or feedback.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>gatsby</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A longawaited fix to a legacy project | Devlog #1</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Sun, 23 Aug 2020 20:19:21 +0000</pubDate>
      <link>https://dev.to/sunnysingh/a-longawaited-fix-to-a-legacy-project-devlog-1-4081</link>
      <guid>https://dev.to/sunnysingh/a-longawaited-fix-to-a-legacy-project-devlog-1-4081</guid>
      <description>&lt;p&gt;👨🏼‍💻 📹 In this devlog, you will follow along with me as I work on a project that I haven't updated in 3 long years.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://devne.ws/"&gt;Devnews&lt;/a&gt; is a developer news aggregation website that I created 4 years ago and still use to this day. However, it broke about a year ago due to an issue with the GitHub trending repositories page crawler. I initially created the project using React, Material UI, localForage, WrapAPI, and Webpack. The static website host used for deployment is Surge.&lt;/p&gt;

&lt;p&gt;Will I be able to fix the issue? Does the project even still run on my machine or able to be deployed? Watch to find out.&lt;/p&gt;




&lt;p&gt;Full episode is also available to &lt;a href="https://youtu.be/-WKjxdfblI8"&gt;watch on YouTube&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Templating repetitive code with Hygen</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Wed, 19 Feb 2020 13:33:23 +0000</pubDate>
      <link>https://dev.to/sunnysingh/templating-repetitive-code-with-hygen-54i7</link>
      <guid>https://dev.to/sunnysingh/templating-repetitive-code-with-hygen-54i7</guid>
      <description>&lt;p&gt;Adding a new feature to a project typically relies on a repetitive set of steps; create new folders with layouts, components, boilerplates, etc. from existing configurations. Most developers will typically handle these repetitions by copying a previous feature and modifying it to the needs of the new one.&lt;/p&gt;

&lt;p&gt;The process of sifting through features to figure out which one is ideal to copy, and then making sure to change all names that reference that exisiting feature and modifying multiple configuration files becomes tedious and inefficient.&lt;/p&gt;

&lt;p&gt;Tools exist to help with this process known as scaffolding. You create a generic template that can then be reused to create new features from. Integrating them is usually not trivial, and so even though there's a long-term productivity benefit most developers choose to keep moving along with the copy-and-paste approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  👊 A new challenger approaches!
&lt;/h2&gt;

&lt;p&gt;I recently started researching different scaffolding tools, and was well aware of the popular &lt;a href="https://yeoman.io/"&gt;Yeoman&lt;/a&gt; one but wanted to find something newer that focused on simplicity of integration. My priority was to immediately get going with a few templates.&lt;/p&gt;

&lt;p&gt;This is when I came across &lt;a href="http://www.hygen.io/"&gt;Hygen&lt;/a&gt;. It met my goal of simplicity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hygen init self
npx hygen generator new feature
npx hygen feature new MyFeature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a few commands, we can create a generator for new features. It creates a &lt;code&gt;_templates&lt;/code&gt; folder in the project, and the &lt;code&gt;npx hygen&lt;/code&gt; command generates files based on those templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗺 Co-location
&lt;/h2&gt;

&lt;p&gt;I'm a fan of the design decisions made for Hygen. One of them is the co-location of templates and metadata:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Templates are located within your project.&lt;/li&gt;
&lt;li&gt;Metadata for the template (e.g. where the file will be outputted) is located within the template using frontmatter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that you don't have to create separate repos, config files, or fancy CLI tools. Just make a folder and run Hygen.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 A quick start
&lt;/h2&gt;

&lt;p&gt;Let's create a React component generator. This will require &lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt; to be installed.&lt;/p&gt;

&lt;p&gt;First, install Hygen as a development dependency of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;hygen &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would be weird if we didn't use Hygen to generate the templates, so we can do that now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hygen init self &lt;span class="c"&gt;# only run this once&lt;/span&gt;
npx hygen generator new component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool, this generates a file to &lt;code&gt;_templates/component/new/hello.ejs.t&lt;/code&gt;. Edit this file to be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
to: src/components/&amp;lt;%= name %&amp;gt;.js
---
import React from 'react'

export function &amp;lt;%= name %&amp;gt;({ children }) {
  return (
    &amp;lt;div&amp;gt;{children}&amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's run our new generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hygen component new ProfileBox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✨ A new component was generated! Check out &lt;code&gt;src/components/ProfileBox.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ProfileBox&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While a very basic example, you can see how within a few minutes you could save yourself time in the long-term for repetitive code within your project.&lt;/p&gt;

&lt;p&gt;I was speculative on whether Hygen could handle more complex use cases, but I was able to generate multiple files for an API client by reading from an OpenAPI JSON specification file. This is all thanks to Hygen's ability to run its &lt;a href="http://www.hygen.io/templates#helpers-and-inflections"&gt;own helpers&lt;/a&gt; alongside your custom ones that can be written using Node.js. It also has support for &lt;a href="http://www.hygen.io/templates#shell"&gt;shell commands&lt;/a&gt;, &lt;a href="http://www.hygen.io/templates#injection"&gt;file injection&lt;/a&gt;, &lt;a href="http://www.hygen.io/generators#interactive-prompt"&gt;interactive prompts&lt;/a&gt;, and &lt;a href="http://www.hygen.io/generators#documenting-your-generators"&gt;self documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The one limitation that I found was lack of asynchronous helper support, so that may limit some really advanced use cases. However at that point, you're better off creating a custom Node.js script and then passing that data off to Hygen.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 What will you automate?
&lt;/h2&gt;

&lt;p&gt;There are so many repetitive tasks in modifying codebases that can be automated with Hygen, so I would love to hear some ideas on how you might use it. I mentioned the API client generator, but I also added commands to a documentation site to generate new tutorials and pages easily. I would start off with some simpler templates, and create more as they become a part of your development workflow.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Got paid $0 for a 3 months client project</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Sun, 26 Jan 2020 00:27:44 +0000</pubDate>
      <link>https://dev.to/sunnysingh/got-paid-0-for-a-3-months-client-project-g5j</link>
      <guid>https://dev.to/sunnysingh/got-paid-0-for-a-3-months-client-project-g5j</guid>
      <description>&lt;p&gt;I share a story of how I did not get paid for doing a 3 months long project for a client.&lt;/p&gt;

&lt;p&gt;Has anyone else here had freelance foes like this? My goal is to prevent others from making the same mistakes that I did because I have heard similar stories from my friends.&lt;/p&gt;

&lt;p&gt;This is from &lt;a href="https://sunnycommutes.fm/episodes/75-got-paid-usd0-for-a-3-months-client-project-Kq5xjK"&gt;Sunny Commutes podcast episode 75&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>podcast</category>
      <category>beginners</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Simplify JavaScript Promises</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Fri, 27 Dec 2019 15:58:52 +0000</pubDate>
      <link>https://dev.to/sunnysingh/simplify-javascript-promises-4djb</link>
      <guid>https://dev.to/sunnysingh/simplify-javascript-promises-4djb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I love promises. Not from people, but from JavaScript.&lt;br&gt;
&lt;a href="https://twitter.com/intent/tweet?text=%22I%20love%20promises.%20Not%20from%20people%2C%20but%20from%20JavaScript.%22%0A%0Ahttps%3A%2F%2Fdev.to%2Fsunnysingh%2Fsimplify-javascript-promises-4djb%0A%0Acc%20%40sunnysinghio&amp;amp;related=sunnysinghio"&gt;Tweet Quote&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I love promises. Not from people, but from JavaScript. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promises&lt;/a&gt; make your code concise and simple, resulting in easier to understand codebases.&lt;/p&gt;

&lt;p&gt;You may also be familiar with the &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await"&gt;async/await&lt;/a&gt; syntax, but unfortunately it causes some headaches. I'll walk through some techniques that solve common scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining &lt;code&gt;async/await&lt;/code&gt; with &lt;code&gt;Promise.then&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The first problem that I encountered is the verbosity of using &lt;code&gt;fetch&lt;/code&gt;:&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're relying solely on just using &lt;code&gt;await&lt;/code&gt;, then you will end up using multiple variables and lines for very simple use cases.&lt;/p&gt;

&lt;p&gt;Instead, we can take advantage of the "traditional" &lt;code&gt;Promise.then&lt;/code&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A one-liner that is still readable and functions the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining &lt;code&gt;async/await&lt;/code&gt; with &lt;code&gt;Promise.catch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The second problem that I encountered is the scope created with &lt;code&gt;try { }&lt;/code&gt; blocks:&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Oh no, `data` is undefined 😱&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmm... we can't read &lt;code&gt;data&lt;/code&gt; outside of the &lt;code&gt;try { }&lt;/code&gt; block. If you're new to the &lt;code&gt;const&lt;/code&gt; variable I suggest you read my &lt;a href="https://dev.to/blog/javascript-const"&gt;demystifying const variables&lt;/a&gt; article, but essentially this variable is scoped to only be used inside of its curly braces &lt;code&gt;{ }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One thing we could do is to lift the variable up:&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;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Now we can use `data` 😎&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But... we are no longer within the safe bounds of using &lt;code&gt;const&lt;/code&gt; variables. Anywhere later on in the code, &lt;code&gt;data&lt;/code&gt; could get reassigned and we'd be spending hours debugging. Is there a way to get the same result while still using &lt;code&gt;const&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Why yes, there is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// We can still use `data` 👍&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're again taking advantage of two syntaxes for a Promise: &lt;code&gt;async/await&lt;/code&gt; and &lt;code&gt;Promise.catch&lt;/code&gt;. If &lt;code&gt;fetchData&lt;/code&gt; resolves successfully, then that value is set to the &lt;code&gt;data&lt;/code&gt; variable as usual. Otherwise, the &lt;code&gt;data&lt;/code&gt; variable gets set to &lt;code&gt;null&lt;/code&gt; which is what gets returned inside of &lt;code&gt;.catch()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor wisely
&lt;/h2&gt;

&lt;p&gt;When a new language feature comes out, developers rush to make their codebase follow that new syntax. As you saw in this article, this is not always wise. Combining older syntax with the new can be a powerful way to keep your codebase simple and easy to understand for anyone new to it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Traditional vs modern web development ⚔️</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Tue, 02 Jul 2019 11:48:37 +0000</pubDate>
      <link>https://dev.to/sunnysingh/traditional-vs-modern-web-development-1em8</link>
      <guid>https://dev.to/sunnysingh/traditional-vs-modern-web-development-1em8</guid>
      <description>&lt;p&gt;Modern web development. We all have a love and hate relationship with it because while it revolutionized web development practices, it also greatly complicated them.&lt;/p&gt;

&lt;p&gt;I'd like to go over a few aspects of modern web development and explain the benefits that I've been able to appreciate. I will also mention when you would still want to do things the traditional way.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Managing packages
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The old way&lt;/strong&gt;: Manually downloading package files into a &lt;code&gt;vendor&lt;/code&gt; folder or linking a CDN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The modern way&lt;/strong&gt;: Using package managers like &lt;a href="https://www.npmjs.com/"&gt;npm&lt;/a&gt; or &lt;a href="https://yarnpkg.com/"&gt;Yarn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;: Being able to manage all of your packages with &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, and &lt;code&gt;remove&lt;/code&gt; commands not only saves time, but also keeps track of things like outdated or unsecure packages. The one downside is the large number of files those packages end up depending on and so you may still consider it better to link a package from a CDN for very simple sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎮 Building user interfaces
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The old way&lt;/strong&gt;: Manually manipulating the DOM using &lt;a href="https://jquery.com/"&gt;jQuery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The modern way&lt;/strong&gt;: Rendering entire UIs with JavaScript using &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; or &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;: Breaking out your UI into components and state can be a huge productivity boost plus it also helps to reduce bugs. I talked a lot about this in my &lt;a href="https://sunnysingh.io/blog/declarative"&gt;Declarative all the things!&lt;/a&gt; article. There is also a huge benefit in a static architecture like &lt;a href="https://jamstack.org/"&gt;JAMStack&lt;/a&gt; for simplified deployment. Keep in mind that while large apps become easier to maintain, manual DOM manipulation is still great for building out something on the spot with zero external dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎁 Bundling code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The old way&lt;/strong&gt;: Concatenation and minification tools to manually declare how files get merged together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The modern way&lt;/strong&gt;: Using &lt;code&gt;import&lt;/code&gt; statements and a bundler like &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;: While this was a huge pain point initially, bundling tools have gotten much easier to work with now. You can start writing JS and CSS using the latest features including &lt;code&gt;import&lt;/code&gt; statements, and the code will automatically get transformed and bundled. This is important not only for cross-browser compatibility but also performance, so even in situations where you can depend on users having the latest browsers you probably still want to use a bundler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extras&lt;/strong&gt;: CLI tools for frameworks abstract away bundling for you, so that you don't have to worry about it. See &lt;a href="https://facebook.github.io/create-react-app/"&gt;Create React App&lt;/a&gt;, &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, &lt;a href="https://cli.vuejs.org/guide/creating-a-project.html"&gt;Vue CLI&lt;/a&gt;, and &lt;a href="https://nuxtjs.org/"&gt;Nuxt.js&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the number of choices? 🤯
&lt;/h2&gt;

&lt;p&gt;It's true, web development is considered complex nowadays due to the sheer number of decisions we have to make. This becomes especially overwhelming for anyone new that is trying to learn everything.&lt;/p&gt;

&lt;p&gt;However, one skill that I believe every developer should possess is deciding what is worth learning and using. Don't immediately install that new framework you read about in a Medium article unless it solves a particular problem for you that another, more community-supported one isn't already solving.&lt;/p&gt;

&lt;p&gt;I hope to provide more resources for helping you become smarter about those decisions. If you're still wondering which JavaScript framework to use, check out my &lt;a href="https://sunnycommutes.fm/episodes/62-why-is-everyone-using-react-K0EAQo"&gt;Why is everyone using React?&lt;/a&gt; podcast episode.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published to &lt;a href="https://sunnysingh.io/news"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Declarative all the things!</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Fri, 14 Jun 2019 12:35:31 +0000</pubDate>
      <link>https://dev.to/sunnysingh/declarative-all-the-things-3ea0</link>
      <guid>https://dev.to/sunnysingh/declarative-all-the-things-3ea0</guid>
      <description>&lt;p&gt;I'm basically the hype person from that "all the things!" meme when it comes to declarative programming, but that recently got me thinking in how common the declarative/imperative terminology actually is among both junior and senior level developers.&lt;/p&gt;

&lt;p&gt;Luckily, I got a few good albeit mixed responses to this question on Twitter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We learned both styles first year of University.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/JamesIvings/status/1105671627675787264"&gt;@JamesIvings&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;Quite senior in my case&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/cullophid/status/1105717103116603392"&gt;@cullophid&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;Coming from a non-computer science background, I started coming across these terms relatively recently in my web development career (15+ years).&lt;/p&gt;

&lt;p&gt;Also, I’ve worked with a lot of folks with computer science backgrounds, and I can’t recall a single time we used imperative and declarative terminology for anything.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/LashaKrikheli/status/1109586323634118656"&gt;@LashaKrikheli&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the most part, it depends on whether you self learned programming, in which case these terms may not be so common. However, Lasha points out that it's not even common among those who have computer science degrees.&lt;/p&gt;

&lt;p&gt;Personally, this is terminology that I started using a ton once I learned about it, but it's definitely a form of jargon even to those within the industry. I initially came across the word "declarative" on React's website which they still use today:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Declarative views make your code more predictable and easier to debug.&lt;br&gt;
— &lt;a href="https://reactjs.org/"&gt;reactjs.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If it's complex jargon though, should we stop using it?&lt;/p&gt;

&lt;h2&gt;
  
  
  But wait, what is declarative anyway?
&lt;/h2&gt;

&lt;p&gt;To write in a &lt;strong&gt;declarative&lt;/strong&gt; style, your code should explain &lt;strong&gt;what&lt;/strong&gt; you want to happen.&lt;/p&gt;

&lt;p&gt;Let's use React as an example. I want a button to change text when it's clicked, so I'd write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setClicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isClicked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicked!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if you're not familiar with React, the code is easy to follow due to its declarative nature.&lt;/p&gt;

&lt;p&gt;You could do the same in an &lt;strong&gt;imperative&lt;/strong&gt; style, but then your code would explain &lt;strong&gt;how&lt;/strong&gt; you'd want it to happen.&lt;/p&gt;

&lt;p&gt;This means that you'd use the DOM to select elements and update manually. 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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#myButton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;event&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;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicked!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compared to the declarative example, the imperative one is doing a lot of manual work in selecting elements and updating them.&lt;/p&gt;

&lt;p&gt;Let's see another example with something a bit more familiar: loops.&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;letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;index&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;letter&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// a, b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I looped through the &lt;code&gt;letters&lt;/code&gt; array and created a new &lt;code&gt;filtered&lt;/code&gt; array without the letter "c". Do you see something wrong with this? It's actually an &lt;strong&gt;imperative&lt;/strong&gt; style, which is something that you want to avoid especially with the amount of code for a simple task.&lt;/p&gt;

&lt;p&gt;Let's see a &lt;strong&gt;declarative&lt;/strong&gt; example:&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;letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// a, b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woah, what happened? Declarative happened. Manually looping over an array just to filter a value out is too much of &lt;strong&gt;how&lt;/strong&gt;. Instead, you want to describe &lt;strong&gt;what&lt;/strong&gt; you want, which is exactly what the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter"&gt;Array.filter&lt;/a&gt; method allows you to do.&lt;/p&gt;

&lt;p&gt;Hopefully at this point, you understand not only the differences between declarative and imperative styles, but also the benefits that declarative code can provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talk declarative to me
&lt;/h2&gt;

&lt;p&gt;Jargon, despite its negative connotations, is a quite useful communication tool. When I'm reviewing someone else's code, it's much easier to suggest they make it more declarative than to provide specific explanations and examples. It essentially can save a lot of time in discussing code when everyone are familiar with the imperative and declarative patterns and terminology.&lt;/p&gt;

&lt;p&gt;The unfortunate realization that I've had is that these terms are not quite popular, making it confusing jargon rather than useful jargon.&lt;/p&gt;

&lt;p&gt;The solution? I would say more usage of these terms to introduce it into common programming vocabulary, as well as articles and tutorials on how code can be written in both imperative and declarative ways.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published to &lt;a href="https://sunnysingh.io/news"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>codequality</category>
      <category>programming</category>
      <category>devtips</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Demystifying "const" variables in JavaScript</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Sun, 09 Jun 2019 14:56:40 +0000</pubDate>
      <link>https://dev.to/sunnysingh/demystifying-const-variables-in-javascript-2jfo</link>
      <guid>https://dev.to/sunnysingh/demystifying-const-variables-in-javascript-2jfo</guid>
      <description>&lt;p&gt;By now, ES6 (ES2015) is widespread enough that many developers are writing their JavaScript with this modern syntax. However, I commonly see room for improvement with variable declarations. Specifically, when I see a &lt;code&gt;let&lt;/code&gt; to declare an object that is updated, but never reassigned a new value.&lt;/p&gt;

&lt;p&gt;Here is the offending example:&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;let&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// We never reassign cache to a different value.&lt;/span&gt;
&lt;span class="c1"&gt;// It's a reference to the same object.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Yes, that can actually be a &lt;code&gt;const&lt;/code&gt; because the &lt;code&gt;cache&lt;/code&gt; variable is never reassigned.&lt;/p&gt;
&lt;h2&gt;
  
  
  Immutability vs Reassignment
&lt;/h2&gt;

&lt;p&gt;Many refer to &lt;code&gt;const&lt;/code&gt; declarations as creating "immutable" variables. Immutable meaning that the value (including properties of objects) can never be updated.&lt;/p&gt;

&lt;p&gt;If that is the case, then let's try our initial example using a &lt;code&gt;const&lt;/code&gt;:&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// will output "hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If &lt;code&gt;cache&lt;/code&gt; is now an immutable, non-changeable constant, then attempting to add an &lt;code&gt;id&lt;/code&gt; property to it will not work or even throw an error.&lt;/p&gt;

&lt;p&gt;However, if you try running that example, it will work perfectly fine. The string "hello" will be logged, which is retrieved from the updated object.&lt;/p&gt;

&lt;p&gt;Okay, so if &lt;code&gt;const&lt;/code&gt; does not declare something as immutable, what does it do? Well, a &lt;strong&gt;&lt;code&gt;const&lt;/code&gt; prevents a variable from being reassigned a new value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are a few examples of reassigning variables:&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;let&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// reassigning variable to a new object&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// reassigning variable to false boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Changing any of the above &lt;code&gt;let&lt;/code&gt; statements to &lt;code&gt;const&lt;/code&gt; instead will throw a type error: "Uncaught TypeError: Assignment to constant variable."&lt;/p&gt;

&lt;p&gt;Setting a property on an object, or updating an existing property, is &lt;strong&gt;not&lt;/strong&gt; reassignment. The value of the variable is still the same object, and you are updating the properties of that object.&lt;/p&gt;
&lt;h2&gt;
  
  
  Benefit of using &lt;code&gt;const&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Hopefully you understand how &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; differ now, but that probably still begs one major question: why should I care enough to use &lt;code&gt;const&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It mainly comes down to the quality of your code, and how much information you or another developer can infer from it. For example, as I'm looking through one file in a codebase, I see this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Okay, so it's a variable that declares whether some operation succeeded or not, in this case it has since the value is &lt;code&gt;true&lt;/code&gt;. However, the &lt;code&gt;let&lt;/code&gt; also tells me that this variable can be reassigned to &lt;code&gt;false&lt;/code&gt; anywhere later on in that file.&lt;/p&gt;

&lt;p&gt;To double check, I search for all instances of &lt;code&gt;isSuccess&lt;/code&gt; in the file. Hmm, it's not reassigned anywhere, so I know that this variable's value will remain &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sounds like a constant to me, and if this variable was actually declared as a &lt;code&gt;const&lt;/code&gt; then I wouldn't have to search anywhere else in the file for it.&lt;/p&gt;

&lt;p&gt;Now imagine you revisit this code a few months later. Way down in the file, you add this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Uh oh, you potentially caused a bug just now because when you initially wrote this code for &lt;code&gt;isSuccess&lt;/code&gt; to be &lt;code&gt;true&lt;/code&gt;, you weren't expecting anyone to change it later on. Even &lt;a href="https://sunnysingh.io/blog/readable-code"&gt;your future self&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is an extremely common scenario, especially in large codebases with multiple developers. The great part is that this is easily solved by using &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; appropriately.&lt;/p&gt;
&lt;h2&gt;
  
  
  Default to &lt;code&gt;const&lt;/code&gt;, but use &lt;code&gt;let&lt;/code&gt; when necessary
&lt;/h2&gt;

&lt;p&gt;As a common rule, I suggest using &lt;code&gt;const&lt;/code&gt; to declare all new variables, and when you come across a point where you need to reassign one of those variables, then change it to a &lt;code&gt;let&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's a much bigger example of how you might use both properly:&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&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;user&lt;/span&gt; &lt;span class="o"&gt;=&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;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The `cache` variable is never reassigned a new value.&lt;/span&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hello`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The `user` variable is not reassigned a new value right now.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="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;// Here, we assign `user` and `isSuccess` new values.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It's definitely a paradigm shift to declare variables with &lt;code&gt;const&lt;/code&gt; instead of &lt;code&gt;var&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt;, but it can add more confidence to your code. Try it out and let me know what you think.&lt;/p&gt;

&lt;p&gt;Want to learn how to improve your code even further? You might like my &lt;a href="https://sunnysingh.io/blog/readable-code"&gt;Writing code for your future self&lt;/a&gt; article.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/sunnysingh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ifi0Kfnv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--O7OuXbcO--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/14721/90a9a8b4-ce8b-4513-ab5b-2514e9f5aed3.jpg" alt="sunnysingh image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/sunnysingh/writing-code-for-your-future-self-3da2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Writing code for your future self&lt;/h2&gt;
      &lt;h3&gt;Sunny Singh ・ Feb  2 '19 ・ 4 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tips&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#learning&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>codequality</category>
    </item>
    <item>
      <title>My favorite design resources</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Mon, 27 May 2019 12:41:22 +0000</pubDate>
      <link>https://dev.to/sunnysingh/my-favorite-design-resources-4ele</link>
      <guid>https://dev.to/sunnysingh/my-favorite-design-resources-4ele</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally published to &lt;a href="https://sunnysingh.io/news"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I don't consider myself a designer, I see design as an extremely important skill to have whether you're building an app, creating brand assets, producing content, or even making flyers to support a local event. Here are some of my favorites resources related to design.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼 Creating &amp;amp; editing images
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pvh-_Rnn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b9pj2ueloryhpc5bi7zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pvh-_Rnn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b9pj2ueloryhpc5bi7zj.png" alt="My personal brand logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to creating images from scratch or doing touch-ups to an existing one, I recommend &lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt; and &lt;a href="https://www.pixelmator.com/pro/"&gt;Pixelmator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past I've used &lt;a href="https://www.designer.io/"&gt;Gravit Designer&lt;/a&gt; which is still a great alternative to vector design apps like Adobe Illustrator and &lt;a href="https://www.sketchapp.com/"&gt;Sketch&lt;/a&gt;. Figma has been slowly gaining popularity and because it is web based, it makes it almost trivial to start creating logos and prototyping user interfaces. Pixelmator is unfortunately a Mac-only desktop app, but I like it as a much cheaper alternative to Photoshop.&lt;/p&gt;

&lt;p&gt;I designed my personal logo (shown above) myself using Gravit, and I recently &lt;a href="https://twitter.com/sunnysinghio/status/1104785318904020993"&gt;tweeted a new podcast artwork&lt;/a&gt; that I'm working on with Figma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus tools&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pablo.buffer.com/"&gt;Pablo&lt;/a&gt;: I use Pablo to quickly create images for social media, such as whenever I share one of my new articles.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.remove.bg/"&gt;remove.bg&lt;/a&gt;: This is a mind-blowing tool for removing backgrounds from photos.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://duotones.co/"&gt;Duotone&lt;/a&gt;: If you want to quickly create a captivating background, Duotone let's you upload a photo and add different effects to it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://squoosh.app/"&gt;Squoosh&lt;/a&gt;: I highly suggest you use an image compressing tool like Squoosh to keep your image sizes small, especially when embedded on websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  👤 Icons and illustrations
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L7mylp6u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qhwphf630jigw8ml92u0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L7mylp6u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qhwphf630jigw8ml92u0.png" alt="My 404 page illustration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing that I definitely lack in is being able to design icons or draw illustrations. Thankfully there are tons of resources from other designers who provide these types of assets to you for free.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://feathericons.com/"&gt;Feather icons&lt;/a&gt;: A clean and simple icon set that I use for just about everything. You can easily include it into React apps using the &lt;a href="https://github.com/feathericons/react-feather"&gt;React Feather&lt;/a&gt; package or just download the raw SVG icons.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react-kawaii.now.sh/"&gt;React Kawaii&lt;/a&gt;: If you need a quick package of reusable components to add some cuteness to your apps, this is it. I have this implemented in a few places on my site such as my &lt;a href="https://sunnysingh.io/404"&gt;404 page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.openmoji.org/"&gt;OpenMoji&lt;/a&gt;: Like emojis? Instead of resorting to the native Apple ones, I recommend you use this unified set that also provides a search and open source license.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://undraw.co/"&gt;unDraw&lt;/a&gt;: A &lt;em&gt;massive&lt;/em&gt; list of pre-made illustrations for different use cases.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.humaaans.com/"&gt;humaaans&lt;/a&gt;: Another great package of assets for mixing-and-matching with different scenes and characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔼 Leveling up your design game
&lt;/h2&gt;

&lt;p&gt;As I mentioned before, I don't see myself as a designer, but I still really enjoy pleasant and intuitive designs. Being passionate about something allows you to take inspiration from the world around you, such as from Apple's minimal design patterns.&lt;/p&gt;

&lt;p&gt;What's great about minimal design is that it's not that hard to learn. Remove less important elements from a user interface, add whitespace, use a consistent and small color palette, and chances are you're not that far off from a clean interface.&lt;/p&gt;

&lt;p&gt;I redesigned my personal website at the end of last year, and &lt;a href="https://sunnysingh.io/blog/revamping-personal-site-gatsby"&gt;wrote about my design decisions&lt;/a&gt;. What's mentioned in that article is the amazing &lt;a href="https://refactoringui.com/"&gt;Refactoring UI&lt;/a&gt; resource which I learned a lot from in keeping my design simple and readable. I also highly recommend these &lt;a href="https://twitter.com/i/moments/880688233641848832?lang=en"&gt;UX tips from Steve Schoger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It takes time to learn how to improve the UX (user experience) of a website or app that you're building. It also takes time to learn how to properly brand and grow a &lt;a href="https://sunnysingh.io/blog/personal-brand"&gt;personal brand&lt;/a&gt;. The important thing is wanting to improve and hopefully some of the resources that I shared here can help you some way.&lt;/p&gt;

</description>
      <category>design</category>
      <category>resources</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Investing in the right technologies to avoid technical debt</title>
      <dc:creator>Sunny Singh</dc:creator>
      <pubDate>Tue, 16 Apr 2019 11:59:49 +0000</pubDate>
      <link>https://dev.to/sunnysingh/investing-in-the-right-technologies-to-avoid-technical-debt-2c06</link>
      <guid>https://dev.to/sunnysingh/investing-in-the-right-technologies-to-avoid-technical-debt-2c06</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally published to &lt;a href="https://sunnysingh.io/news"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a common joke in the JavaScript community that a new framework or library gets released every single day. True or not, it's funny because it definitely seems like that is the case. With so many new things to learn, how can you possibly keep up? Or should you?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h9T-jvZd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bokegu36ga5ynhf0e5c8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h9T-jvZd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bokegu36ga5ynhf0e5c8.jpg" alt="A comic about a developer telling everyone to stop everything and move to a new framework because their current one changed slightly"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn patience, not a new framework ⏳
&lt;/h2&gt;

&lt;p&gt;I love keeping up with the latest technologies. In fact, I built a site called &lt;a href="https://devne.ws/"&gt;DevNews&lt;/a&gt; a few years ago in which I still use today for finding new tech and software related articles and products.&lt;/p&gt;

&lt;p&gt;However, there is a big difference between reading up about a new framework versus actually &lt;em&gt;investing time&lt;/em&gt; to learning and potentially even migrating your current code over to it. A lot of the time, it's not worth it because that framework becomes obsolete or even non-existent in a few years.&lt;/p&gt;

&lt;p&gt;I've been bitten by this problem many times in the past, and the best advice that I can give is to &lt;strong&gt;simply be patient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For any big projects that you expect to stay around for at least 5 years, you probably want to observe a framework's community long enough before making the decision to learn and use it. Consider the time that you put in to learning a specific framework or tool to be an investment. That return on investment should be a positive one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The story of AngularJS and React ⚔️
&lt;/h2&gt;

&lt;p&gt;Do you remember AngularJS? Many developers were using it around 5 years ago, and it was deemed the go-to framework for making a dynamic website or entire web app. It was even backed by Google, so what could go wrong?&lt;/p&gt;

&lt;p&gt;Angular 2 was announced and it was completely different from the first version. In fact, backwards compatibility was not an available option early on. Thus the usage of React, a competing option from Facebook, grew.&lt;/p&gt;

&lt;p&gt;I personally worked on an AngularJS project, but I never invested into it deeply. I was skeptical and continued to build my own projects the traditional way (a monolithic Laravel backend with a jQuery and Bootstrap frontend). Fast forward and I am now building multiple React apps.&lt;/p&gt;

&lt;p&gt;I believe that this is the correct approach. Use the tools and technologies that work well for you until you know for sure that there is a better way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cool cool... but how do I know when there is a better way?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Avid DEV reader&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ah, I'm glad you asked. I did an entire podcast episode about this topic! While I talk about React specifically, the principles (community, efficiency, and longevity) apply to any framework or tool. Recommend you check it out 👇&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎧 &lt;a href="http://sunny.link/pod62"&gt;Listen to the podcast&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📺 &lt;a href="https://youtu.be/J1FO-2pRGDE"&gt;Watch the video&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, a large community size means more resources available to you for debugging issues and finding accompanying libraries. Even in the case of Angular, there are still tons of resources out there to continue maintaining those projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: How do you manage to stay on top of technical debt, or how have you been bitten by it in the past?&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>tips</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
