<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Furkan Emin Can's Tech Blog]]></title><description><![CDATA[I'm a self-taught, passionate front-end developer who enjoys writing TypeScript and strives to become a better developer.]]></description><link>https://femincan.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1695464512502/vT9INi7Og.png</url><title>Furkan Emin Can&apos;s Tech Blog</title><link>https://femincan.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 04:25:55 GMT</lastBuildDate><atom:link href="https://femincan.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How I Built My Custom Blog With Astro and Headless Hashnode]]></title><description><![CDATA[Hi everyone! In this article, I will share my journey of making my custom blog with Astro and Headless Hashnode in one week.
For a long time, I thought about making my blog with my stack, but I don't want to lose the beauties Hashnode offers us. When...]]></description><link>https://femincan.dev/how-i-built-my-custom-blog-with-astro-and-headless-hashnode</link><guid isPermaLink="true">https://femincan.dev/how-i-built-my-custom-blog-with-astro-and-headless-hashnode</guid><category><![CDATA[Web Development]]></category><category><![CDATA[HeadlessHashnode]]></category><category><![CDATA[HeadlessChallenge]]></category><dc:creator><![CDATA[Furkan Emin Can]]></dc:creator><pubDate>Mon, 30 Oct 2023 21:41:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698700643483/bd3568bc-1b59-4170-883f-e2fcec7445f1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone! In this article, I will share my journey of making my custom blog with Astro and Headless Hashnode in one week.</p>
<p>For a long time, I thought about making my blog with my stack, but I don't want to lose the beauties Hashnode offers us. When I saw the announcement on Headless Hashnode, I was fascinated. I thought that now was the time to build my custom blog.</p>
<p>I want to make it with Astro. Lately, I have seen the framework many times, and I've wondered about it. Also, at least, I should learn how to create queries in GraphQL. After these thoughts, I just postponed.</p>
<p>Once I saw <a class="user-mention" href="https://hashnode.com/@danielapassos">Daniela Passos</a>'s tweet, I thought this was a great opportunity to overcome procrastination and take action immediately.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/danizeres/status/1716446318606876713">https://twitter.com/danizeres/status/1716446318606876713</a></div>
<p> </p>
<p>Before I start telling you about my journey, here are the links to the live preview and project repository:</p>
<p><strong>Live Preview:</strong> <a target="_blank" href="https://headless-personal-blog.netlify.app/">https://headless-personal-blog.netlify.app</a><br /><strong>Project Repository:</strong> <a target="_blank" href="https://github.com/femincan/personal-blog">https://github.com/femincan/personal-blog</a></p>
<h2 id="heading-planning-and-preparation">Planning and Preparation</h2>
<p>For the blog, I will use these tools:</p>
<ul>
<li><p><strong>Astro:</strong> I will build the blog on top of this framework, and I am planning to use Solid.js for the interactive parts.</p>
</li>
<li><p><strong>Tailwind CSS:</strong> I like utility classes and I will use the Daisy UI component library with it.</p>
</li>
</ul>
<p>I've used Tailwind CSS and Daisy UI before, but this is my first time with Astro.</p>
<p><a target="_blank" href="https://docs.astro.build/en/tutorial">The official Astro tutorial</a> is a great starting point. So I started with it and finished it in three days. I loved the tutorial, it helps you to quickly get used to Astro.</p>
<p>To be able to get the data, I need to use GraphQL queries and I've never used GraphQL before. Luckily, I don't need to create a GraphQL server from scratch, I just need to learn how to query an existing server.</p>
<h2 id="heading-starting-development">Starting Development</h2>
<p>After finishing the tutorial, I think I am ready to start developing the blog.</p>
<h3 id="heading-setting-up-the-project">Setting Up the Project</h3>
<p>To scaffold the project, I've used the official <code>create-astro</code> CLI.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698382064438/c844d91a-5f1e-4b68-82a8-d9ff4ee7702a.png" alt="Terminal screenshot after selecting create-astro cli options." class="image--center mx-auto" /></p>
<p>Let me explain the options I choose above:</p>
<ol>
<li><p>I chose the name <strong>blog</strong> for the project folder. (After a while later, I changed it to <strong>personal-blog</strong>.)</p>
</li>
<li><p>I chose to create an empty Astro project. I want to build from scratch.</p>
</li>
<li><p>I prefer it installs the dependencies for me. (I've used <strong>pnpm</strong> as package manager.)</p>
</li>
<li><p>I chose to use TypeScript for the project with the recommended <strong>strict</strong> restriction options.</p>
</li>
</ol>
<h3 id="heading-setting-up-developer-productivity-tools">Setting Up Developer Productivity Tools</h3>
<p>I like using <strong>ESLint</strong> and <strong>Prettier</strong> in my projects. Also <strong>Husky</strong> with <strong>lint-staged</strong> for linting the staged files before every commit.</p>
<p>In Astro setting up ESLint and Prettier was very easy. You only need to install <code>eslint-plugin-astro</code> for linting and <code>prettier-plugin-astro</code> for formatting. Then, just follow the instructions in their documentation.</p>
<p><strong>Note:</strong> If you are using VSCode with ESLint and Prettier extensions, don't forget to insert the code below into your <code>settings.json</code> file to enable them to work with <code>.astro</code> files.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"prettier.documentSelectors"</span>: [<span class="hljs-string">"**/*.astro"</span>],
  <span class="hljs-attr">"eslint.validate"</span>: [<span class="hljs-string">"astro"</span>]
}
</code></pre>
<h3 id="heading-creating-fetcher-functions">Creating Fetcher Functions</h3>
<p>Before creating pages, I wrote four fetcher functions:</p>
<p><strong>1.</strong> <code>getBlogData</code>: The function fetches the required information about the blog and the author.</p>
<p><strong>2.</strong> <code>getLatestPosts</code>: The function fetches the information about the latest six posts.</p>
<p>When you fetch the first six posts the API already gives you to latest six posts, so I don't need to do additional processing on the returned posts.</p>
<p><strong>3.</strong> <code>getAllPosts</code>: This function is a bit more complicated because I have to fetch all the blog posts in the blog to be able to generate static post pages with <code>getStaticPaths</code> function of Astro.</p>
<p>Hashnode API doesn't give you all the posts. The maximum limit is twenty posts per fetch. You can fetch two more properties alongside the posts: <code>hasNextPage</code> and <code>endCursor</code>.</p>
<p>So we can give <code>endCursor</code> to the <code>after</code> parameter in the next fetch to be able to fetch another at most twenty posts if <code>hasNextPage</code> property is <code>true</code>.</p>
<p>I used a while loop and fetched twenty posts in each iteration until the value of <code>hasNextPage</code> is <code>false</code>.</p>
<p><strong>4.</strong> <code>getAboutPageData</code>: The function fetches the content of the static <code>blog</code> page in my blog.</p>
<p>Using GraphQL queries looks intuitive. But I can't say the same for the response. It looks cluttered. Even so, a bit of normalization fixes this issue.</p>
<h3 id="heading-creating-base-layout">Creating Base Layout</h3>
<p>Astro lets you create shared layouts for pages. I used this feature to create a base layout. It is a wrapper for every page on the website.</p>
<p>It takes the current page information like title and description as props and uses them for Meta tags.</p>
<p>It starts with a Navbar component, the page content in the middle, and a Footer component at the bottom.</p>
<h3 id="heading-creating-pages">Creating Pages</h3>
<p>Because the time is limited, I want to keep the number of pages low.</p>
<p>The website will consist of four pages:</p>
<ol>
<li><p><code>/</code>: Shows the information about the author and the list of latest blog posts.</p>
</li>
<li><p><code>/blog</code>: Shows the list of all blog posts.</p>
</li>
<li><p><code>/blog/[slug]</code>: Shows the blog post by the post slug.</p>
</li>
<li><p><code>/about</code>: Shows the static <code>about</code> page of my blog.</p>
</li>
</ol>
<h4 id="heading-1-the-home-page">1. The Home Page</h4>
<p>The home page consists of two sections:</p>
<ol>
<li><p>The author area</p>
</li>
<li><p>The latest blog post list</p>
</li>
</ol>
<p>For the author area, I am fetching the data with <code>getBlogData</code> function and passed its author prop to <code>AuthorArea</code> component.</p>
<p>For the latest blog posts, fetched the six latest blog posts with <code>getLatestPosts</code> function and passed them to <code>PostList</code> component.</p>
<p>In the <code>PostList</code> component, I used Astro's <code>Image</code> component. I think having an <code>Image</code> component in a framework provides great development experience. Auto-optimized images, no cumulative layout shift, and so on.</p>
<p>With this I've done with the home page, Let's continue to the blog page.</p>
<h4 id="heading-2-the-blog-home-page">2. The Blog Home Page</h4>
<p>The page shows the list of all posts. I used <code>getAllPosts</code> function and showed the response using <code>PostList</code> component that I've used on the home page.</p>
<h4 id="heading-3-the-individual-blog-posts-page">3. The Individual Blog Post's Page</h4>
<p>The page uses the <code>getStaticPaths</code> function to generate all individual blog post pages.</p>
<p>For the content of the page, <a target="_blank" href="https://docs.astro.build/en/guides/markdown-content/#fetching-remote-markdown">Astro doesn't support remote Markdown.</a> This means I have to convert the markdown to HTML by myself.</p>
<p>I created the <code>convertMarkdown</code> function for this purpose and used:</p>
<ul>
<li><p><code>remark</code> for parsing markdown,</p>
</li>
<li><p><code>rehype</code> for converting parsed markdown to HTML,</p>
</li>
<li><p><code>highlight.js</code> for code highlighting.</p>
</li>
</ul>
<p>When converting markdown to HTML, I've encountered a problem because of the images in the fetched markdown.</p>
<p>The images in the fetched markdown look like the below:</p>
<pre><code class="lang-markdown">![<span class="hljs-string">ReferenceError: Cannot access 'cherry' before initialization</span>](<span class="hljs-link">https://cdn.hashnode.com/res/hashnode/image/upload/v1686747528090/a420f21e-cd58-404d-8de1-b07a6ef99ce3.png align="center"</span>)
</code></pre>
<p>There is an <code>align</code> property at the end of the link of the image. This property causes the images not to be parsed and converted correctly.</p>
<p>So, before parsing and converting the markdown, I wrote the code below to remove <code>align</code> properties from images.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> cleanedContent = content.replace(<span class="hljs-regexp">/\salign="\w*"(?=\))/g</span>, <span class="hljs-string">''</span>);
</code></pre>
<p>After finishing the function, I created a <code>Markdown</code> component that is responsible for displaying the markdown using <code>@tailwindcss/typography</code> plugin to show the converted markdown on the page.</p>
<p>After a few changes to its appearance, the post displayed nicely on the page.</p>
<h4 id="heading-4-the-about-page">4. The About Page</h4>
<p>On the page, I fetched the content of <code>about</code> page in my blog with <code>getAboutPageData</code> function. Then, I used <code>Markdown</code> component again to show this content.</p>
<h3 id="heading-rss-feed-sitemapxml-and-robotstxt">RSS Feed, Sitemap.xml, and Robots.txt</h3>
<p>Astro has a great integration system. Most integrations are ready to use for your needs. For example, I added Tailwind CSS to my blog via a short <code>astro add tailwindcss</code> command.</p>
<p>With this system, I easily added:</p>
<ul>
<li><p>RSS feed by using <code>@astrojs/rss</code> package,</p>
</li>
<li><p>generated <code>sitemap.xml</code> by using <code>@astrojs/sitemap</code> package,</p>
</li>
<li><p>and created <code>robots.txt</code> by using <code>astro-robots-txt</code> package.</p>
</li>
</ul>
<p>After all this, I think the blog is ready to deploy.</p>
<h2 id="heading-deployment">Deployment</h2>
<p>I chose Netlify for deploying the blog. After selecting the blog repo the blog was automatically built and deployed. Netlify also auto-deploys when new commits are pushed to the blog repo.</p>
<p>To keep the blog up to date, I used <a target="_blank" href="https://docs.netlify.com/configure-builds/build-hooks">Netlify build hooks</a> in combination with Hashnode webhooks. Netlify build hooks provide a URL, and making a POST request to this URL, triggers a website rebuild and deployment.</p>
<p>With Hashnode Webhook, when a post is published, updated, or deleted, Hashnode makes a POST request to this URL, triggering the blog to rebuild with fresh content.</p>
<p>That's all!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I am happy with Hashnode already for my blog. Additionally, the new Headless Hashnode fills the gap in the front-end customization side of a blog. Now you can use which stack you want for your blog.</p>
<p>My experience with Astro has been nearly flawless. I only faced some issues with TypeScript that the TypeScript Intellisense stopped working when I moved from <code>.ts</code> file to <code>.astro</code> file. But, compared to its good points, this problem is quite acceptable.</p>
<p>This challenge helped me to continue writing on my blog and overcome my procrastination. Thanks, Hashnode for that.</p>
<p>Feel free to specify your thoughts in the comments.</p>
<p>See you in the next one!</p>
<hr />
<h2 id="heading-stay-in-touch">Stay in Touch</h2>
<ul>
<li><p><a target="_blank" href="https://twitter.com/femincan">Twitter</a></p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/femincan">LinkedIn</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/femincan">GitHub</a></p>
</li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://gql.hashnode.com">Hashnode GraphQL Playground</a></p>
</li>
<li><p><a target="_blank" href="https://apidocs.hashnode.com/">Hashnode Public API Docs</a></p>
</li>
<li><p><a target="_blank" href="https://docs.astro.build">Astro Documentation</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Variable Declaration in JavaScript: A Comprehensive Guide]]></title><description><![CDATA[Declaring variables is what we do most in JavaScript. Knowing the inside of the variable declaration process gives you more idea about it. For example, if you are new to JavaScript, the behavior of var statement likely to be confusing for you.
Throug...]]></description><link>https://femincan.dev/variable-declaration-in-javascript-a-comprehensive-guide</link><guid isPermaLink="true">https://femincan.dev/variable-declaration-in-javascript-a-comprehensive-guide</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Furkan Emin Can]]></dc:creator><pubDate>Fri, 11 Aug 2023 04:53:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691610816923/895112f6-e501-4552-9ea1-a582b555b271.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Declaring variables is what we do most in JavaScript. Knowing the inside of the variable declaration process gives you more idea about it. For example, if you are new to JavaScript, the behavior of <code>var</code> statement likely to be confusing for you.</p>
<p>Through this article, you will learn how to declare, and mutate variables using <code>var</code>, <code>let</code>, and <code>const</code> statements, and have a better understanding of the differences between them.</p>
<p>I will explain each concept in two parts:</p>
<ol>
<li><p>Before ES6 (<code>var</code> statement)</p>
</li>
<li><p>After ES6 (<code>let</code> and <code>const</code> statements)</p>
</li>
</ol>
<p><strong>Let's dive into these statements:</strong></p>
<h2 id="heading-declaring-variables-with-hoisting-in-mind">Declaring Variables with Hoisting in Mind</h2>
<p>When you declare variables in your app, the interpreter moves them to the top of their scope and allocates places in the memory before the execution starts. This process is called <strong>Hoisting</strong>.</p>
<h3 id="heading-1-variable-declaration-with-var-statement"><strong>1. Variable declaration with</strong> <code>var</code> <strong>statement:</strong></h3>
<p>When you declare a variable with <code>var</code> statement, it is initialized in the memory as <code>undefined</code> before the code execution. So, you can use the variable before declaring it, but it returns <code>undefined</code>.</p>
<p>When execution starts and reaches the line that the variable is declared, replaces the value in the memory with the value of the variable.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(strawberry); <span class="hljs-comment">// undefined</span>

<span class="hljs-keyword">var</span> strawberry = <span class="hljs-string">'🍓'</span>;

<span class="hljs-built_in">console</span>.log(strawberry); <span class="hljs-comment">// 🍓</span>
</code></pre>
<p>With this behavior, the program runs without errors. However, in some cases, this can lead to unexpected results.</p>
<h3 id="heading-2-variable-declaration-with-let-and-const-statements"><strong>2. Variable declaration with</strong> <code>let</code> <strong>and</strong> <code>const</code> <strong>statements:</strong></h3>
<p>When you declare a variable with <code>let</code> or <code>const</code> statements the variable is allocated in the memory as <strong>uninitialized</strong> in the <em>temporal dead zone</em>. You cannot use variables in the <em>temporal dead zone</em> before their declaration. So, if you try to use a variable before declaring it, the program returns an error.</p>
<p>When the program reaches the line where the variable is declared, it initializes the variable with that value.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(cherry); <span class="hljs-comment">// ReferenceError</span>

<span class="hljs-keyword">const</span> cherry = <span class="hljs-string">"🍒"</span>;

<span class="hljs-built_in">console</span>.log(cherry); <span class="hljs-comment">// 🍒</span>
</code></pre>
<p>If you try to run this code snippet, you will see an error similar to below. Because we try to access a variable in the <em>temporal dead zone</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686747528090/a420f21e-cd58-404d-8de1-b07a6ef99ce3.png" alt="ReferenceError: Cannot access 'cherry' before initialization" class="image--center mx-auto" /></p>
<h2 id="heading-understanding-variable-scopes">Understanding Variable Scopes</h2>
<p>In JavaScript:</p>
<ul>
<li>Everything between curly braces is <em>block scope</em>,</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686751970366/36dbfa36-7edc-4e18-b9f3-20fce69a4767.png" alt="A code snippet screenshot visualizes the block scope term in JavaScript." class="image--center mx-auto" /></p>
<ul>
<li>Everything inside a function is <em>function scope</em>.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1691122652143/e12f1b1a-17ca-435c-9514-de21e51caff3.png" alt="A code snippet screenshot visualizes the function scope term in JavaScript." class="image--center mx-auto" /></p>
<h3 id="heading-1-scope-of-var-statement"><strong>1. Scope of</strong> <code>var</code> <strong>statement</strong></h3>
<p>Variables declared with <code>var</code> statement are available globally. (If they are not declared in a function.) So, you can use the variables declared inner scope is in outer scopes and vice-versa:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Global Scope</span>
<span class="hljs-keyword">var</span> carrot = <span class="hljs-string">"🥕"</span>;

<span class="hljs-comment">// Inner Scope</span>
{
  <span class="hljs-built_in">console</span>.log(carrot); <span class="hljs-comment">// 🥕</span>

  <span class="hljs-built_in">console</span>.log(tomato); <span class="hljs-comment">// undefined</span>

  <span class="hljs-comment">// More Inner Scope</span>
  {
    <span class="hljs-built_in">console</span>.log(carrot); <span class="hljs-comment">// 🥕</span>

    <span class="hljs-keyword">var</span> tomato = <span class="hljs-string">"🍅"</span>;
  }

  <span class="hljs-built_in">console</span>.log(tomato); <span class="hljs-comment">// 🍅</span>
}
</code></pre>
<p>As you can see from the code snippet:</p>
<ol>
<li><p>We were able to use the <code>carrot</code> variable declared in the most outer (global) scope in the inner scopes.</p>
</li>
<li><p>We were able to use <code>tomato</code> variable declared in the inner scope in the outer scopes.</p>
</li>
</ol>
<p>❗ Variables declared with <code>var</code> statement in a function are only available in the <em>function scope</em>, and cannot be used outside of it.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Function Scope</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">declareMelon</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> watermelon = <span class="hljs-string">"🍉"</span>;
}

<span class="hljs-built_in">console</span>.log(watermelon); <span class="hljs-comment">// ReferenceError</span>
</code></pre>
<h3 id="heading-2-scope-of-let-and-const-statements"><strong>2. Scope of</strong> <code>let</code> <strong>and</strong> <code>const</code> <strong>statements:</strong></h3>
<p>The variables declared with <code>let</code> and <code>const</code> statements are only available in <em>block scope</em>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> banana = <span class="hljs-string">"🍌"</span>;

<span class="hljs-comment">// Block Scope</span>
{
  <span class="hljs-built_in">console</span>.log(banana); <span class="hljs-comment">// 🍌</span>

  <span class="hljs-keyword">let</span> lemon = <span class="hljs-string">"🍋"</span>;

  <span class="hljs-comment">// Inner Block Scope</span>
  {
    <span class="hljs-built_in">console</span>.log(banana); <span class="hljs-comment">// 🍌</span>
    <span class="hljs-built_in">console</span>.log(lemon); <span class="hljs-comment">// 🍋</span>
  }
}

<span class="hljs-built_in">console</span>.log(lemon); <span class="hljs-comment">// ReferenceError</span>
</code></pre>
<p>As you can see in the last line, you cannot use a variable created in the inner scope in the outer scopes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686814208553/7a633e42-44df-4055-8af4-e0ac58201806.png" alt="ReferenceError: lemon is not defined" class="image--center mx-auto" /></p>
<h2 id="heading-mutating-variables">Mutating Variables</h2>
<p>This time the parts will change, the first group involves <code>var</code> and <code>let</code> statements and the second involves <code>const</code> statement. Because <code>var</code> and <code>let</code> statements are mutable, and <code>const</code> statement is immutable.</p>
<h3 id="heading-1-mutation-in-var-and-let-statements"><strong>1. Mutation in</strong> <code>var</code> <strong>and</strong> <code>let</code> <strong>statements.</strong></h3>
<p>As I said <code>var</code> and <code>let</code> statements are mutable, so you can assign new values to the variables declared with them.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> pepper = <span class="hljs-string">"🌶️"</span>;
<span class="hljs-keyword">let</span> apple = <span class="hljs-string">"🍏"</span>;

pepper = <span class="hljs-string">"🫑"</span>;
apple = <span class="hljs-string">"🍎"</span>;

<span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🫑</span>
<span class="hljs-built_in">console</span>.log(apple); <span class="hljs-comment">// 🍎</span>
</code></pre>
<p>Additionally, you can mutate a variable from inner scopes:</p>
<ul>
<li><p>For <code>let</code> statement, the variable will change in the scope where the declaration is made.</p>
</li>
<li><p>For <code>var</code> statement, the variable will change globally. (or in <em>functional scope.</em>)</p>
</li>
</ul>
<pre><code class="lang-javascript">{
  pepper = <span class="hljs-string">"🌶️"</span>;
  apple = <span class="hljs-string">"🍏"</span>;

  <span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🌶️</span>
  <span class="hljs-built_in">console</span>.log(apple); <span class="hljs-comment">// 🍏</span>
}

<span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🌶️</span>
<span class="hljs-built_in">console</span>.log(apple); <span class="hljs-comment">// 🍏</span>
</code></pre>
<h3 id="heading-2-mutation-in-const-statement"><strong>2. Mutation in</strong> <code>const</code> <strong>statement</strong></h3>
<p>Variables declared with <code>const</code> statement are immutable. So you cannot re-assign them.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> strawberry = <span class="hljs-string">"🍓"</span>;

strawberry = <span class="hljs-string">"🍉"</span>; <span class="hljs-comment">// TypeError</span>
</code></pre>
<p>If you try to run the code snippet above, the program throws an error similar to below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687697471389/1a7b0d00-407e-46de-a420-356f4e0c61e3.png" alt="TypeError: Assignment to constant variable." class="image--center mx-auto" /></p>
<p><strong>❗Important Note: You cannot mutate arrays and objects via assignment but can mutate them via their methods, and property assignment.</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fruitsArray = [<span class="hljs-string">"🍎"</span>, <span class="hljs-string">"🍐"</span>];
<span class="hljs-keyword">const</span> fruitsObject = {
  <span class="hljs-attr">apple</span>: <span class="hljs-string">"🍎"</span>,
  <span class="hljs-attr">pear</span>: <span class="hljs-string">"🍐"</span>,
};

fruitsArray[<span class="hljs-number">2</span>] = <span class="hljs-string">"🍒"</span>; <span class="hljs-comment">// [ '🍎', '🍐', '🍒' ]</span>
fruitsArray.push(<span class="hljs-string">"🍌"</span>); <span class="hljs-comment">// [ '🍎', '🍐', '🍒', '🍌' ]</span>

fruitsObject.cherry = <span class="hljs-string">"🍒"</span>; <span class="hljs-comment">// { apple: '🍎', pear: '🍐', cherry: '🍒' }</span>
</code></pre>
<h2 id="heading-redeclaring-variables">Redeclaring Variables</h2>
<p>Strangely, we can redeclare variables declared with <code>var</code> statement using the same name. This is another error-prone characteristic of <code>var</code> statement. Fortunately, this behavior has changed with <code>let</code> and <code>const</code> statements.</p>
<h3 id="heading-1-redeclaration-with-var-statement"><strong>1. Redeclaration with</strong> <code>var</code> <strong>statement:</strong></h3>
<p>You can redeclare a variable declared with <code>var</code> statement in the same scope or inner-outer scopes.</p>
<p>As I said before, variables declared with <code>var</code> statement are global, so if you even redeclare a variable in the inner scope (again, except for functional scopes), the variable will change in all scopes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> pepper = <span class="hljs-string">"🌶️"</span>;

<span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🌶️</span>

<span class="hljs-comment">// Inner Scope</span>
{
  <span class="hljs-keyword">var</span> pepper = <span class="hljs-string">"🥦"</span>;

  <span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🥦</span>
}

<span class="hljs-built_in">console</span>.log(pepper); <span class="hljs-comment">// 🥦</span>
</code></pre>
<p>As you can see in the code snippet, This behavior tends to cause big problems. Because someone working in the same codebase, unintentionally may declare a variable using the same name used before.</p>
<h3 id="heading-2-redeclaration-with-let-and-const-statements"><strong>2. Redeclaration with</strong> <code>let</code> <strong>and</strong> <code>const</code> <strong>statements:</strong></h3>
<p>You cannot redeclare variables declared with <code>let</code> or <code>const</code> statements in the same scope. If you try the program throws an error.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> eggplant = <span class="hljs-string">"🍆"</span>;

<span class="hljs-keyword">let</span> eggplant = <span class="hljs-string">"🥔"</span>; <span class="hljs-comment">// SyntaxError</span>
</code></pre>
<p>But you can redeclare the variables in inner scopes. Because, as I said before, the variables declared with <code>let</code> and <code>const</code> statements are <em>block scope</em> and don't affect the outer scopes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> carrot = <span class="hljs-string">"🥕"</span>;

<span class="hljs-comment">// Block Scope</span>
{
  <span class="hljs-keyword">const</span> carrot = <span class="hljs-string">"🍒"</span>;

  <span class="hljs-built_in">console</span>.log(carrot); <span class="hljs-comment">// 🍒</span>
}

<span class="hljs-built_in">console</span>.log(carrot); <span class="hljs-comment">// 🥕</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Today ES6 statements are the default choice for variable declaration in JavaScript. Nevertheless, the <code>var</code> statement might still be encountered, especially in older apps. In this guide, you have learned the differences between <code>var</code>, <code>let</code>, and <code>const</code> statements, hoisting and scope in variable declaration.</p>
<p>Thank you for taking the time to read this article. If you have any questions, or thoughts feel free to comment.</p>
<p>See you in the next one!</p>
<hr />
<h2 id="heading-stay-in-touch">Stay in Touch</h2>
<ul>
<li><p><a target="_blank" href="https://twitter.com/femincan">Twitter</a></p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/femincan">LinkedIn</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/femincan">GitHub</a></p>
</li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://dev.to/lydiahallie/javascript-visualized-hoisting-478h">JavaScript Visualized: Hoisting</a> by <em>Lydia Hallie</em></p>
</li>
<li><p><a target="_blank" href="https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd">JavaScript Visualized: Scope (Chain)</a> by <em>Lydia Hallie</em></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Hoisting">Hoisting</a> by <em>MDN Web Docs</em></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Setup React App with Parcel and TypeScript]]></title><description><![CDATA[Parcel is a zero-config build tool with great out-of-the-box development experience and scalable architecture.
I experimented with Parcel in my previous project and I am happy with the result. (The second project of the Front End Development Librarie...]]></description><link>https://femincan.dev/how-to-setup-react-app-with-parcel-and-typescript</link><guid isPermaLink="true">https://femincan.dev/how-to-setup-react-app-with-parcel-and-typescript</guid><category><![CDATA[React]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Furkan Emin Can]]></dc:creator><pubDate>Mon, 29 May 2023 03:01:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685284902862/c139bf26-c98c-4bf1-947a-b77dd5a5de73.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Parcel is a zero-config build tool with great out-of-the-box development experience and scalable architecture.</p>
<p>I experimented with Parcel in my previous project and I am happy with the result. (The second project of the Front End Development Libraries Curriculum of FreeCodeCamp.)</p>
<p>The setup process was a bit difficult. Thus, I will guide you to simplify this process in this article.</p>
<p><strong>Note: To access the completed boilerplate, you can visit the</strong> <a target="_blank" href="https://github.com/femincan/react-parcel-ts-boilerplate"><strong>react-parcel-ts-boilerplate</strong></a><strong>.</strong></p>
<h2 id="heading-1-installing-dependencies">1. Installing Dependencies</h2>
<p>I have used npm for this boilerplate. But feel free to use any package manager you choose.</p>
<p>First, you need to install <code>react</code> and <code>react-dom</code> as dependencies.</p>
<pre><code class="lang-bash">npm i react react-dom
</code></pre>
<p>Next, you need <code>parcel</code> and <code>typescript</code> packages as development dependencies, also since this is a TypeScript project, you need type definitions for <code>react</code> and <code>react-dom</code>.</p>
<pre><code class="lang-bash">npm i -D parcel typescript @types/react @types/react-dom
</code></pre>
<h2 id="heading-2-configuring-tsconfigjson">2. Configuring <code>tsconfig.json</code></h2>
<p>The documentation says that:</p>
<blockquote>
<p>Parcel supports TypeScript out of the box without any additional configuration.</p>
</blockquote>
<p>When you try to run or build the app there is no problem. Yet, I consistently encountered TypeScript errors with IntelliSense.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684591191226/00fe4c5b-eecb-4969-85f0-1b76883cde28.png" alt="Screenshot showing the error message: 'Cannot use JSX unless the --jsx flag is provided'." class="image--center mx-auto" /></p>
<p>In order to address these issues, I recommend using the following <code>tsconfig.json</code> file, as this configuration helped me resolve those issues:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"compilerOptions"</span>: {
    <span class="hljs-attr">"module"</span>: <span class="hljs-string">"ESNext"</span>,
    <span class="hljs-attr">"target"</span>: <span class="hljs-string">"ESNext"</span>,
    <span class="hljs-attr">"moduleResolution"</span>: <span class="hljs-string">"node"</span>,
    <span class="hljs-attr">"lib"</span>: [<span class="hljs-string">"DOM"</span>, <span class="hljs-string">"ESNext"</span>],
    <span class="hljs-attr">"jsx"</span>: <span class="hljs-string">"react-jsx"</span>
  }
}
</code></pre>
<h2 id="heading-3-creating-base-files">3. Creating Base Files</h2>
<p>You need to create these three files in the <code>src</code> directory:</p>
<p><strong>1.</strong> <code>App.tsx</code>: This file serves as the root component of the app.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> &lt;div&gt;App&lt;/div&gt;;

<span class="hljs-keyword">export</span> { App };
</code></pre>
<p><strong>2.</strong> <code>index.tsx</code>: This file is responsible for rendering the <code>App</code> component into the <code>&lt;div id="app"&gt;</code> element on the page.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> { App } <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'app'</span>) <span class="hljs-keyword">as</span> HTMLElement);

root.render(&lt;App /&gt;);
</code></pre>
<p><strong>3.</strong> <code>index.html</code>: This file serves as the entry point for the app.</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React (Parcel + TypeScript)<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"index.tsx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-4-configuring-packagejson">4. Configuring <code>package.json</code></h2>
<p>Make sure to add the <code>source</code> property in the <code>package.json</code> (No need for the <code>main</code> property.), and set its value as the path to the <code>index.html</code> file.</p>
<pre><code class="lang-json"><span class="hljs-string">"source"</span>: <span class="hljs-string">"src/index.html"</span>
</code></pre>
<p>Additionally, in order to run the app using scripts, you need to add the necessary scripts to the <code>package.json</code> file.</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-attr">"start"</span>: <span class="hljs-string">"parcel"</span>,
  <span class="hljs-attr">"build"</span>: <span class="hljs-string">"parcel build"</span>
}
</code></pre>
<h2 id="heading-5-running-the-app">5. Running the App</h2>
<p>Since the app is ready, you can run it with <code>start</code> script:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<h3 id="heading-the-failed-to-install-modules-error">The "failed to install modules" Error</h3>
<p>You may come across the following error, which I encountered when using pnpm in my previous project:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684591908120/549386f3-7c5b-4d34-a097-a998ca911f3f.png" alt="Screenshot showing the error message: 'Failed to install process: pnpm failed to install modules'." class="image--center mx-auto" /></p>
<p>To resolve this issue, add the <code>process</code> property under the <code>alias</code> property in the <code>package.json</code> file and set its value to <code>false</code>.</p>
<pre><code class="lang-json"><span class="hljs-string">"alias"</span>: {
  <span class="hljs-attr">"process"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Developing a React project with Parcel and TypeScript can present challenges, particularly on the TypeScript side. However, using this boilerplate was beneficial in my previous project, and I believe it can assist you as well.</p>
<p>Thank you for reading. Feel free to share your thoughts about Parcel in the comments section.</p>
<p>See you in the next one!</p>
<hr />
<h2 id="heading-stay-in-touch"><strong>Stay in Touch</strong></h2>
<ul>
<li><p><a target="_blank" href="https://twitter.com/femincan"><strong>Twitter</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/femincan"><strong>LinkedIn</strong></a></p>
</li>
<li><p><a target="_blank" href="https://github.com/femincan"><strong>GitHub</strong></a></p>
</li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://parceljs.org/docs">Parcel Documentation</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Use SWR for Better Data Fetching Approach]]></title><description><![CDATA[In React, external data is very important to make your project more dynamic. However, when you use useEffect for data fetching, it is generally hard to manage the state, fortunately SWR simplifies this process.
Introduction to SWR
The first thing I w...]]></description><link>https://femincan.dev/how-to-use-swr-for-better-data-fetching-approach</link><guid isPermaLink="true">https://femincan.dev/how-to-use-swr-for-better-data-fetching-approach</guid><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Furkan Emin Can]]></dc:creator><pubDate>Mon, 22 May 2023 04:41:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684986334642/abd0c98b-8146-4a52-bbc1-6fb14f948681.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In React, external data is very important to make your project more dynamic. However, when you use <code>useEffect</code> for data fetching, it is generally hard to manage the state, fortunately SWR simplifies this process.</p>
<h2 id="heading-introduction-to-swr">Introduction to SWR</h2>
<p>The first thing I want to say is what SWR means.</p>
<p>According to its documentation:</p>
<blockquote>
<p>The name “SWR” is derived from <code>stale-while-revalidate</code>, a HTTP cache invalidation strategy popularized by <a target="_blank" href="https://tools.ietf.org/html/rfc5861">HTTP RFC 5861</a>. SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.</p>
</blockquote>
<p><strong>So, SWR is a library that provides React hooks for data fetching.</strong></p>
<h2 id="heading-implementing-swr-in-your-project-my-experience">Implementing SWR in Your Project: My Experience</h2>
<p>I recently completed the first project for the <a target="_blank" href="https://www.freecodecamp.org/learn/front-end-development-libraries">Front End Libraries Certification</a> of FreeCodeCamp. I tried SWR in this project and will share my experience.</p>
<p><strong>Note:</strong> For more information, you can check the project's <a target="_blank" href="https://github.com/femincan/quote-factory">GitHub repository</a> and <a target="_blank" href="https://codesandbox.io/p/github/femincan/quote-factory/main">CodeSandbox</a>.</p>
<p><strong>I used TypeScript for this project, but I will give you examples with JavaScript. So, don't worry if you don't know TypeScript. (I highly recommend it if you don't know.)</strong></p>
<h3 id="heading-1-creating-fetcher-function">1. Creating <code>fetcher</code> function</h3>
<p>I was planning to use Axios for the requests, so I created the async function below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fetcher = <span class="hljs-keyword">async</span> (url) =&gt; {
  <span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> axios.get(url);

  <span class="hljs-keyword">return</span> data;
};
</code></pre>
<p>This function is just a wrapper for the <code>get</code> method of Axios. It accepts a <code>url</code> parameter and returns <code>data</code>.</p>
<h3 id="heading-2-creating-a-hook-that-fetches-a-random-quote">2. Creating a hook that fetches a random quote</h3>
<p>Based on the section <a target="_blank" href="https://swr.vercel.app/docs/getting-started#make-it-reusable"><strong>Make It Reusable</strong></a> in SWR documentation, I created a hook called <code>useRandomQuote</code>.</p>
<p><strong>Note:</strong> In this project, I used <a target="_blank" href="https://github.com/lukePeavey/quotable">Quotable API</a> for random quotes.</p>
<p>This hook is a wrapper for <code>useSWR</code> hook.</p>
<p>In my case, the API returns an array with one element which is the random quote. Since <code>data</code> is <code>undefined</code> during the request, I used <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#optional_chaining_with_expressions">optional chaining</a>.</p>
<p>And, the hook returns an object that contains the <code>quote</code> variable with the variables destructured from <code>useSWR</code> hook.</p>
<p><strong>Let's check the code and inspect it:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> useSWR <span class="hljs-keyword">from</span> <span class="hljs-string">'swr/immutable'</span>;

<span class="hljs-keyword">const</span> useRandomQuote = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { data, ...restSWR } = useSWR(
    <span class="hljs-string">'https://api.quotable.io/quotes/random'</span>,
    fetcher
  );

  <span class="hljs-keyword">return</span> {
    ...restSWR,
    <span class="hljs-attr">quote</span>: data?.[<span class="hljs-number">0</span>],
  };
};

<span class="hljs-keyword">export</span> { useRandomQuote };
</code></pre>
<p>In your projects, you almost always use <code>useSWR</code> hook.</p>
<p><strong>Take a closer look at the useSWR hook:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { data, error, isValidating, isLoading, mutate} = useSWR(
  key,
  fetcher
);
</code></pre>
<ul>
<li><p>Firstly we imported <code>useSWR</code> hook.</p>
</li>
<li><p>Then we used it in our custom hook with two parameters: <code>key</code> and <code>fetcher</code>.</p>
<p>  <code>key</code> is a unique string for the request which is like an id.</p>
<p>  <code>fetcher</code> is an async function that accepts <code>key</code> and returns <code>data</code>.</p>
</li>
<li><p>Finally, it returns <code>data</code>, <code>error</code>, <code>isValidating</code>, <code>isLoading</code>, and <code>mutate</code> variables.</p>
<p>  <code>data</code> is the variable returned from <code>fetcher</code>. During the first request, it will be <code>undefined</code>.</p>
<p>  <code>error</code> is the error thrown by <code>fetcher</code>. If there is no error, it will be <code>undefined</code>.</p>
<p>  <code>isValidating</code> is a boolean that indicates the request's status. It is <code>true</code> during each request including the first request.</p>
<p>  <code>isLoading</code> also is a boolean that indicates the <strong>first</strong> request's status. It is <code>true</code> during the <strong>first</strong> request, then it will always be <code>false</code>.</p>
<p>  <code>mutate</code> is a function that is used to modify the data manually.</p>
</li>
</ul>
<p>If you noticed, I imported <code>useSWR</code> hook from <code>swr/immutable</code> in the first code snippet. It simply disables SWR's auto-revalidation. I prefer to use it because I want to revalidate the data manually with <code>mutate</code> function.</p>
<h4 id="heading-understanding-auto-revalidation">Understanding Auto-Revalidation</h4>
<p>If the data you used is stale, SWR revalidates the data (re-fetches from the server) to keep freshness.</p>
<p>By default, SWR automatically revalidates the data (It assumes that the data is stale) in three cases:</p>
<ol>
<li><p>Every time the component is mounted, even if there is data in the cache, it revalidates.</p>
</li>
<li><p>It revalidates when the window gets focused.</p>
</li>
<li><p>It revalidates when the browser regains its network connection.</p>
</li>
</ol>
<h3 id="heading-3-mutating-the-data">3. Mutating the Data</h3>
<p>If you want manually revalidate the data, you can use <code>mutate</code> function.</p>
<p>I have <code>QuoteCard</code> component that displays the current quote. This component has a <code>New Quote</code> button that handles the mutation of the quote.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> QuoteCard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { quote, isValidating, mutate } = useRandomQuote();

  <span class="hljs-keyword">return</span> (
    {<span class="hljs-comment">/* ... */</span>}
    &lt;button
      <span class="hljs-comment">// ...</span>
      onClick={<span class="hljs-function">() =&gt;</span> mutate()}
    &gt;
      New Quote
    &lt;/button&gt;
    {<span class="hljs-comment">/* ... */</span>}
  )
}
</code></pre>
<p>When the mutate function is called, SWR revalidates the data. During this process, the <code>quote</code> variable remains the same (will not be undefined), and the <code>isValidating</code> variable becomes <code>true</code>.</p>
<p><strong>Here is a diagram of this process:</strong></p>
<p><a target="_blank" href="https://swr.vercel.app/docs/advanced/understanding#fetch-and-revalidate"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684479547020/f6c1e7e2-49ad-408d-9a82-dac0e028d89b.svg" alt="A Diagram illustrating the fetch and revalidate pattern in SWR." class="image--center mx-auto" /></a></p>
<h3 id="heading-4-handling-concurrent-requests">4. Handling Concurrent Requests</h3>
<p>If you don't handle request cancellation manually, the ongoing request continues even if the user initiates a new request alongside it, resulting in multiple concurrent requests.</p>
<p>SWR only updates the data after the last request is completed. If there are concurrent requests, their responses aren't important except for the last one. So if you don't cancel these requests, it results in unnecessary network usage.</p>
<p>I faced the same issue in my project. When the user clicks the <code>New Quote</code> button while a request is still loading, the application triggers a new request alongside the existing one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684849236577/816acb37-d251-457f-9042-39d03eef67cd.gif" alt="Visualization of concurrent requests being triggered by clicking the New Quote button continuously." class="image--center mx-auto" /></p>
<p>Although I checked SWR's documentation, I couldn't find a built-in solution for this issue. (I also checked <a target="_blank" href="https://tanstack.com/query/latest">React Query</a>, and it has a built-in solution for that. I am planning to experiment with it in my next project involving API usage.)</p>
<p>In this scenario, I could use <code>AbortController</code> to handle request cancellation, but I didn't use it to keep things simple. I just disabled the <code>New Quote</code> button during validation.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>SWR helped me a lot in this project. If you have not used it previously, I highly recommend trying it in your future projects.</p>
<p>This is my first blog post, and I will be waiting for your feedback and thoughts about the library in the comments.</p>
<hr />
<h2 id="heading-stay-in-touch">Stay in Touch</h2>
<ul>
<li><p><a target="_blank" href="https://twitter.com/femincan">Twitter</a></p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/femincan">LinkedIn</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/femincan">GitHub</a></p>
</li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://swr.vercel.app/docs">SWR Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://koba04.medium.com/revalidating-options-of-swr-4d9f08bee813">Revalidating options of SWR</a> by <em>Toru Kobayashi</em></p>
</li>
<li><p>My inspiration to use this library comes from <a target="_blank" href="https://www.youtube.com/watch?v=Kjkx2BASAZA">this</a> video by <a target="_blank" href="https://www.youtube.com/@CoderOne">CoderOne</a>. (I know this video is about React Query, but I wanted to try SWR first.)</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>