<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mayank sharma on Medium]]></title>
        <description><![CDATA[Stories by Mayank sharma on Medium]]></description>
        <link>https://medium.com/@mayank2803sharma?source=rss-9e0b2306ad9b------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*FSG8Pnsag4Ku3b9-OEQ3WQ.jpeg</url>
            <title>Stories by Mayank sharma on Medium</title>
            <link>https://medium.com/@mayank2803sharma?source=rss-9e0b2306ad9b------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 02:03:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@mayank2803sharma/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Integrating Data Source with ToolJet to Retrieve and Display Data]]></title>
            <link>https://medium.com/@mayank2803sharma/integrating-data-source-with-tooljet-to-retrieve-and-display-data-457a540026cf?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/457a540026cf</guid>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[tooljet]]></category>
            <category><![CDATA[no-code]]></category>
            <category><![CDATA[no-code-development]]></category>
            <category><![CDATA[mongodb]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Sun, 11 Aug 2024 17:33:24 GMT</pubDate>
            <atom:updated>2024-08-11T17:33:24.551Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GFTpA_Iq7PRXbKifgClayw.png" /><figcaption>ToolJet- a no-code platform to build business applications</figcaption></figure><h3><strong>Introduction</strong></h3><p><strong>ToolJet </strong>is an <strong><em>open-source</em></strong>, <strong><em>low-code</em></strong> platform that enables tools and dashboard development. With its drag-and-drop interface, you can easily connect to various data sources, and build interactive applications without extensive coding.</p><p>Through this blog, I will guide you through the process of integrating ToolJet with <strong><em>data sources</em></strong> (Rest APIs &amp; MongoDB) to retrieve and display data in a user-friendly application.</p><p><strong>We’ll cover the steps:-</strong><br>1) connect data sources to ToolJet<br>2) create queries to fetch data<br>3) display that data using ToolJet’s visual components like tables.</p><p>Let’s roll up our sleeves and dive in!</p><h3><strong>Get Started</strong></h3><p>Open the ToolJet app and sign in or sign up as needed. Once logged in, you’ll be taken to the dashboard where you can start creating or managing your applications.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZQWCn3D-VO2trnnCBoKtJw.png" /><figcaption>Dashboard</figcaption></figure><h3><strong>Integrating ToolJet with REST APIs</strong></h3><p><strong>Step 1: </strong>Navigate to the <strong>Data Sources</strong> tab located on the left-hand side of the interface.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P6iYn793RK3JxNX01gzirg.png" /><figcaption>Data Source</figcaption></figure><p><strong>Step 2:</strong> From the list of available data sources, add <strong>REST API</strong></p><p><strong>Step 3: </strong>Enter the API Details</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LJEI0KkZ_DSRSXLySPSbhA.png" /><figcaption>Configuration Page</figcaption></figure><p>1) In the configuration screen, enter the <strong>Base URL</strong> of the REST API you want to connect to. For example, if you are using a public API like JSONPlaceholder, you would enter <a href="https://jsonplaceholder.typicode.com/">https://jsonplaceholder.typicode.com/.</a></p><p>2) If the API requires authentication or specific headers add them.</p><p>3) If your API uses a specific authentication type like Basic Auth or Bearer Token, select the appropriate option from the dropdown.</p><p>4) Click on <strong>Save </strong>to store the configuration.</p><p><strong>Step 4: </strong>Go to the App section and create an app.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4jGrEMRH0ymx-5mEdtu2Kg.png" /></figure><p><strong>Step 5: </strong>In the Tooljet App-Builder, navigate to the <strong>Queries</strong> tab and click on <strong>Add </strong>and select the REST API data source you just configured.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3uVCg7n_r6AbbiiI7He9FQ.png" /></figure><p><strong>Step 6: </strong>Specify the API endpoint relative to the base URL, choose the HTTP method (usually GET for retrieving data), and add any necessary parameters, body, or headers.<br>For example:- we are using users .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8skEeodJw28sU7rjCOhixQ.png" /></figure><p>Hit Run to check if the data is coming or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T8QteRd2hpeMorZ10as_Dg.png" /></figure><p><strong>Step 7: </strong>From the component section, drag and drop a <strong>Table</strong> component onto the canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qly-DrMEQ48hY4EdZBfcXQ.png" /></figure><p><strong>Step 8: </strong>Remove the pregiven data from <strong>Data </strong>and put <strong>{{queries.restapi1.data}} (</strong>it bind the data returned by the <strong>restapi1 </strong>query to the component, allowing the component to display that specific data.<strong>)</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w2FxzBItUU4xKH70f18DjA.png" /></figure><p>With the API data displayed, you can customize it by editing or deleting columns, or adjusting the Table’s appearance using the Properties or Style sections on the right side.</p><p><strong>Step 9: </strong>Click on the Phone icon and drag the table on the canvas again to make the app responsive.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*97a56tcGCZO7lOa7VEbgTw.png" /></figure><p><strong>Step 10: </strong>Again in the <strong>Data </strong>remove the pregiven data and put <strong>{{queries.restapi1.data}} </strong>and make the necessary changes in table appearance accordingly.</p><p><strong>Step 11: </strong>Click the <strong>Preview</strong> button to see how the data appears in the Table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w8lVWjlrvmcugwzLXMsuBQ.png" /><figcaption>Preview Page</figcaption></figure><h3>Integrating ToolJet with MongoDB</h3><p><strong>Step 1: </strong>Navigate to the Data Sources and choose <strong>MongoDB </strong>from the list of available data sources.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hfPVDHAA-99NLpLUe1KlgQ.png" /></figure><p><strong>Step 2: </strong>Configure the MongoDB settings</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vk3v6pd6vSFKpaKrKBwkKA.png" /><figcaption>MongoDB Configuration Page</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/713/1*aYyfGHjASkB78oL92Mja8g.png" /></figure><ol><li>You have two choices either you can use Manual connection or connect through connection string.</li><li>If you are using Manual connection, Enter all the details like Host, Port etc.</li><li>If you are connection string, enter it.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/719/1*_sAF_ECuMRAy6HIZACHSrQ.png" /></figure><p>After this, click on test connection, when connection is verified, save the configuration.</p><p><strong>Step 3: </strong>Go to the App section and create an app and after that navigate to the Queries tab and click on Add and select the REST API data source you just configured.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RMouWFiQrXVDGiCw-YpA9Q.png" /><figcaption>App Configuration</figcaption></figure><p><strong>Step 4: </strong>Specify the operation, collection name, filter and Operations.<br>for example:- we are going to fetch all the users from the <strong>users </strong>collection.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*06v34WUdq2ykDMSWn0-tkA.png" /></figure><p><strong>Step 5: </strong>Hit Run to see the results</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-1QDaTu2c-8kbJT5gsNXrA.png" /></figure><p><strong>Step 6:</strong> From the component section, drag and drop a Table component onto the canvas, Remove the pregiven data from Data and put <strong>{{queries.mongodb1.data}} (</strong>It binds the data retrieved from the mongodb1 MongoDB query to the component<strong>).</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u_r-kvUXcHr-IiV586kDBg.png" /></figure><p>With the data displayed, you can customize it by editing or deleting columns, or adjusting the Table’s appearance using the Properties or Style sections on the right side.<br>Now you can make the application responsive and phone-adaptive, just like we did with the REST API integration.</p><p><strong>Step 7:</strong> Click the <strong>Preview</strong> button to see how the data appears in the Table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aH3IodMGhWUVa58Hd4HKZA.png" /></figure><h3><strong>Conclusion</strong></h3><p>we explored how to integrate ToolJet with REST APIs and MongoDB, enabling you to create responsive, data-driven applications quickly and easily.<br>Thanks for following along!</p><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=457a540026cf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimizing React: A Deep Dive into the Evolution of React Compiler]]></title>
            <link>https://blog.stackademic.com/optimizing-react-a-deep-dive-into-the-evolution-of-react-compiler-c20a33ce2b8c?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/c20a33ce2b8c</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[compilers]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Thu, 22 Feb 2024 04:17:31 GMT</pubDate>
            <atom:updated>2024-02-22T04:17:31.798Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>React Compiler is no longer a research project. The compiler now powers <strong>Instagram.com</strong> in production and the first open-source release will be out soon.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_UEzrfV50Fo_w-M6xZ2tGQ.jpeg" /></figure><p>The Concept of React Compiler was introduced during <a href="https://www.youtube.com/watch?v=lGEMwh32soc"><strong>React Conf 2021</strong></a><strong>.<br></strong>React Compiler is an ‘Auto-Memoizing Compiler’ that <strong>automates all the memoizations</strong> in your React Application.</p><p><strong>Why do we need it in the first place?</strong></p><p>To understand this, Let’s take an example.</p><pre>function VideoTab({videos,title}){<br>  const uniqueVideos = new Set(videos);<br>  const size = uniqueVideos.size;<br>  <br>  return (<br>    &lt;&gt;<br>      &lt;Heading title={title} size={size}/&gt;<br>      &lt;VideoList videos={uniqueVideos}/&gt;<br>    &lt;/&gt;<br>  )<br>}</pre><p>The code is quite straightforward. It receives <strong>videos </strong>and <strong>titles </strong>as props and then passes the uniqueVideos to &lt;VideoList/&gt; and the title to &lt;Heading/&gt;.<br>UniqueVidoes removes duplicates from the videos and then passes it to the &lt;VideoList/&gt;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/1*hsDtWa1FVfUMYTUSbUbdsQ.png" /><figcaption>Tree Structure of the component</figcaption></figure><p>Now Let’s say we pass a different title as a prop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l9Nk_XPspe3ElRr7fDvyZw.png" /></figure><p>Ideally, We should just render the &lt;Heading/&gt;component, not the &lt;VideoList/&gt;component cause it doesn’t depend upon the title.<br>But <strong>React </strong>generally re-renders everything which is not a good thing in case of complex and big codebase.</p><p>To tackle this we have memorization.</p><h3>What is memorization?</h3><p><strong>memoization</strong> is the process of <em>storing data</em> <em>in the cache</em> and then retrieving this information the next time it is needed.<br>In Simple words, it prevents unnecessary re-rendering of components by storing the results of previous function calls.</p><p><strong>How is memoization currently handled in React?<br></strong>Two main hooks are currently used in React for memoization: useMemo and useCallback.</p><h3><strong>useMemo</strong></h3><p>This hook helps you store the result of a function so you can use it later without recalculating.</p><p>It accepts two arguments:</p><ol><li>A function that calculates the value you want to cache.</li><li>Dependency Array.</li></ol><pre>import { useMemo } from &#39;react&#39;;<br><br>function MyComponent({ number }) {<br>  const squaredNumber = useMemo(() =&gt; {<br>    return (number*number);<br>  }, [number]);<br><br>  return (<br>    &lt;div&gt;<br>      &lt;p&gt;Original number: {number}&lt;/p&gt;<br>      &lt;p&gt;Square: {squaredNumber}&lt;/p&gt;<br>    &lt;/div&gt;<br>  );<br>}</pre><p>In this example, the useMemo hook caches the result of (number*number) <br>So, if the number prop doesn&#39;t change, it won&#39;t recalculate the square, but if number changes, it will recalculate it.</p><h3>useCallback</h3><p>The useCallback hook is very similar to useMemo. The main difference is that useCallback returns a memoized <em>function</em>.</p><p><strong>When to use </strong><strong>useCallbackinstead of </strong><strong>useMemo?</strong></p><p>Every time a component re-renders, its functions get recreated. This means that a component may end up re-rendering even though the function itself didn’t change — it was just recreated when the page re-rendered.</p><p><strong>Sounds Complicated?</strong><br>Let me break it down.</p><ol><li>When you declare a function inside a functional component, each time the component re-renders, a new instance of that function is created. Even though the function might have the same logic, it’s considered a different instance because it’s recreated each time the component renders.</li><li>If you pass functions as props to child components, and these functions are recreated on every render of the parent component, it can lead to unnecessary re-renders of the child components. This can impact performance, especially if these child components are expensive to render.</li></ol><p>To solve this we use useCallback.</p><pre>// App.js<br>import { useState, useCallback } from &quot;react&quot;;<br>import ReactDOM from &quot;react-dom/client&quot;;<br>import Todos from &quot;./Todos&quot;;<br><br>const App = () =&gt; {<br>  const [count, setCount] = useState(0);<br>  const [todos, setTodos] = useState([]);<br><br>  const increment = () =&gt; {<br>    setCount((c) =&gt; c + 1);<br>  };<br>  const addTodo = useCallback(() =&gt; {<br>    setTodos((t) =&gt; [...t, &quot;New Todo&quot;]);<br>  }, [todos]);<br><br>  return (<br>    &lt;&gt;<br>      &lt;Todos todos={todos} addTodo={addTodo} /&gt;<br>      &lt;hr /&gt;<br>      &lt;div&gt;<br>        Count: {count}<br>        &lt;button onClick={increment}&gt;+&lt;/button&gt;<br>      &lt;/div&gt;<br>    &lt;/&gt;<br>  );<br>};<br><br>const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));<br>root.render(&lt;App /&gt;);</pre><pre>// Todos.js<br><br>import { memo } from &quot;react&quot;;<br><br>const Todos = ({ todos, addTodo }) =&gt; {<br>  console.log(&quot;child render&quot;);<br>  return (<br>    &lt;&gt;<br>      &lt;h2&gt;My Todos&lt;/h2&gt;<br>      {todos.map((todo, index) =&gt; {<br>        return &lt;p key={index}&gt;{todo}&lt;/p&gt;;<br>      })}<br>      &lt;button onClick={addTodo}&gt;Add Todo&lt;/button&gt;<br>    &lt;/&gt;<br>  );<br>};<br><br>export default memo(Todos);</pre><p><strong>Let’s use memoization in our starting example.</strong></p><pre>function VideoTab({videos,title}){<br>  const uniqueVideos = useMemo(()=&gt;{<br>    return new Set(videos);<br>  },[videos])<br>  const size = uniqueVideos.size;<br>  <br>  return (<br>    &lt;&gt;<br>      &lt;Heading title={title} size={size}/&gt;<br>      &lt;VideoList videos={uniqueVideos}/&gt;<br>    &lt;/&gt;<br>  )<br>}</pre><p>So now if we send a different title, only the &lt;Heading/&gt;will be re-render.<br>Looks like the problem is solved right?</p><p>Not really. It does solve the problem of re-rendering but manual memoization comes with its own set of drawbacks, including code clutter, potential errors, and ongoing maintenance overhead.</p><p>Ex-&gt;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sECyv9GGzVKsNpaz3hZx0Q.png" /><figcaption>Code Spinnet of BlueSky App</figcaption></figure><h3>React Compiler</h3><p>Now, everything we just learned about useMemo and useCallback may become irrelevant when the React Compiler is released.</p><p>The React Compiler aims to automate the process of optimizing re-renders in React applications. The goal is to automatically re-render only the necessary parts of the UI when the state changes, <em>without compromising on React’s core mental model</em>.</p><p>React Compiler is introduced as an optimizing compiler for React. It leverages knowledge of both JavaScript and React’s rules to safely compile code. React components are expected to follow certain rules.<br>For that Developers are encouraged to enable <strong>Strict Mode</strong> and use <strong>React’s ESLint plugin</strong> to catch subtle bugs and ensure their code follows React’s rules. If the compiler detects code that doesn’t strictly adhere to React’s rules and either compiles it safely or skips compilation if it’s not safe.</p><p>Overall, the announcement highlights Meta’s commitment to improving React’s performance and developer experience, with React Compiler representing a significant step forward in achieving these goals.</p><p>Useful Links:-</p><ol><li><a href="https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024">https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024</a></li><li><a href="https://www.youtube.com/watch?v=kjOacmVsLSE">https://www.youtube.com/watch?v=kjOacmVsLSE</a></li><li><a href="https://www.youtube.com/watch?v=qOQClO3g8-Y">https://www.youtube.com/watch?v=qOQClO3g8-Y</a></li></ol><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><h3>Stackademic 🎓</h3><p>Thank you for reading until the end. Before you go:</p><ul><li>Please consider <strong>clapping</strong> and <strong>following</strong> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><strong>X</strong></a><strong> | </strong><a href="https://www.linkedin.com/company/stackademic"><strong>LinkedIn</strong></a><strong> | </strong><a href="https://www.youtube.com/c/stackademic"><strong>YouTube</strong></a><strong> | </strong><a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a></li><li>Visit our other platforms: <a href="https://plainenglish.io/"><strong>In Plain English</strong></a><strong> | </strong><a href="https://cofeed.app/"><strong>CoFeed</strong></a><strong> | </strong><a href="https://venturemagazine.net/"><strong>Venture</strong></a><strong> | </strong><a href="https://blog.cubed.run/"><strong>Cubed</strong></a></li><li>More content at <a href="https://stackademic.com/"><strong>Stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c20a33ce2b8c" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/optimizing-react-a-deep-dive-into-the-evolution-of-react-compiler-c20a33ce2b8c">Optimizing React: A Deep Dive into the Evolution of React Compiler</a> was originally published in <a href="https://blog.stackademic.com/">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mastering JavaScript Generators: Practical Use Cases]]></title>
            <link>https://blog.stackademic.com/mastering-javascript-generators-practical-use-cases-8bc54d5a0bf0?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/8bc54d5a0bf0</guid>
            <category><![CDATA[iterators]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[generator]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Tue, 20 Feb 2024 05:32:48 GMT</pubDate>
            <atom:updated>2024-02-22T01:48:25.146Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*MqzLOptV8UnmNtVaC8myVw.png" /></figure><p>JavaScript is a versatile programming language that provides various features to help developers write efficient and expressive code. One such feature is <strong>Generator, </strong>which<strong> </strong>brings a new approach to handling async tasks and working with data streams.</p><h3>What are JavaScript Generators?</h3><p>Generators are a special type of function in JavaScript that allows you to control the execution of a function. Unlike regular functions, which run to completion, generators can be paused at any point during their execution and later resumed from where they left off.</p><p>Generator Functions are defined using the syntaxfunction*. It uses something called yieldto pause the execution of the generator function and return a value to the caller. When the generator is resumed, it continues executing from where it was paused.</p><p>When a generator function is called, it returns an iterator object, which can be used to control the function’s execution.</p><p><strong>Let’s take a basic example</strong></p><pre>function* simpleGenerator() {<br>  yield &#39;First yield&#39;;<br>  yield &#39;Second yield&#39;;<br>  return &#39;Generator done&#39;;<br>}<br><br>const gen = simpleGenerator();  // iterator object<br>console.log(gen.next()); // { value: &#39;First yield&#39;, done: false }<br>console.log(gen.next()); // { value: &#39;Second yield&#39;, done: false }<br>console.log(gen.next()); // { value: &#39;Generator done&#39;, done: true }</pre><p>When a generator function is called, it returns something called an <strong>iterator object</strong>.<br>The iterator object has two methods:- next() and return().</p><h3><strong>Next( ) Method</strong></h3><p>The next() method is used to resume the execution of a generator function from where it was paused. It returns an object with two properties: value and done.</p><ul><li>The value property contains the value produced by the yield statement.</li><li>The done property is a boolean indicating whether the generator has completed (true) or is still running (false).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/757/1*PbulzfU0LV9wGMymucsCNw.png" /></figure><h3>Return( ) Method</h3><p>The return() method allows us to force complete a generator function before it reaches the end.</p><p>It also takes an optional argument that will be returned as the final value of the generator.</p><pre>function* simpleGenerator() {<br>  yield 1;<br>  yield 2;<br>  yield 3;<br>}<br><br>const iterator = simpleGenerator();<br>console.log(iterator.next()); // Output: { value: 1, done: false }<br>console.log(iterator.return(&quot;Finished!&quot;)); // Output: { value: &quot;Finished!&quot;, done: true }<br>console.log(iterator.next()); // Output: { value: undefined, done: true }</pre><p>Let’s take some real-world use cases and examples of generators.</p><h3>1) For..of Loop with Generator</h3><p>Let’s say a generator yields a lot of data, the best thing will be to use for..of loop instead of next().</p><pre>function* countTo100(){<br>  for(let i=0;i&lt;100;i++){<br>    yield i;<br>  }<br>}<br>const iterator = countTo100();<br><br>for(const item of iterator){<br>  console.log(item);<br>}<br>// 0 1 2 3 ...</pre><h3>2) Lazy evaluation</h3><p>Let’s say you want a sequence of numbers, but you’re not sure how many. Here’s how a generator helps:</p><pre>function* numberGen(){<br>  let number = 1;<br>  while(true){<br>    yield number++;<br>  }<br>}<br><br>const number = numberGen();<br>console.log(number.next()); // { value: 1, done: false }<br>console.log(number.next()); // { value: 2, done: false }</pre><p>With generators, you get the next number only when you ask for it.</p><h3>3) yield*</h3><p>If we have another generator and need to iterate on that before proceeding with the execution of the current generator function, we can use <strong>yield*</strong></p><p>Let’s take an example:-</p><pre>function* anotherGeneratorFunction() {<br>  yield &#39;A&#39;;<br>  yield &#39;B&#39;;<br>}<br><br>function* generatorFunction() {<br><br>  yield 1;<br><br>  yield* anotherGeneratorFunction();<br><br>  yield 2;<br>  yield 3;<br>}<br>const generator = generatorFunction();<br><br>console.log(generator.next()); // {value: 1, done: false}<br>console.log(generator.next()); // {value: &#39;A&#39;, done: false}<br>console.log(generator.next()); // {value: &#39;B&#39;, done: false}<br>console.log(generator.next()); // {value: 2, done: false}<br>console.log(generator.next()); // {value: 3, done: false}<br>console.log(generator.next()); // {value: undefined, done: true}</pre><p>We have called <strong><em>anotherGeneratorFunction()</em> </strong>with the<strong> yield*</strong>, so it will be executed till the end before proceeding to the execution of <strong>generatorFunction()</strong>.</p><h3>4) Memory utilization</h3><p>Generators don’t hold all the results in memory, they generate them on the fly.</p><p>Imagine you need a sequence of a million numbers. With a regular function, you’d need to store all these numbers in an array, which will consume a significant memory.</p><p>A Generator would be a much more efficient solution in this case.</p><pre>function* bigNumberGen(){<br>  let num = 1;<br>  while(num&lt;=100000000){<br>   yield number++;<br>  }<br>}<br><br>const bigNum = bigNumberGen();<br>const chunk = 10;<br>for(let i=0;i&lt;chunk;i++){<br>  const value = bigNum.next().value();<br>}</pre><h3>5)Handling Async Tasks</h3><p>One of the main advantages of generator functions is their ability to handle asynchronous operations with ease.</p><p>Let’s take a look at an example of how we can use a generator function to handle async operations.</p><pre>function* asyncGenerator() {<br>  try {<br>    const result1 = yield asyncTask1();<br>    console.log(result1);<br><br>    const result2 = yield asyncTask2();<br>    console.log(result2);<br><br>    const result3 = yield asyncTask3();<br>    console.log(result3);<br>  } catch (error) {<br>    console.error(&#39;Error occurred:&#39;, error);<br>  }<br>}<br><br>async function asyncTask1() {<br>  return new Promise(resolve =&gt; {<br>    setTimeout(() =&gt; {<br>      resolve(&#39;Async Task 1 Completed&#39;);<br>    }, 1000);<br>  });<br>}<br><br>async function asyncTask2() {<br>  return new Promise(resolve =&gt; {<br>    setTimeout(() =&gt; {<br>      resolve(&#39;Async Task 2 Completed&#39;);<br>    }, 1500);<br>  });<br>}<br><br>async function asyncTask3() {<br>  return new Promise(resolve =&gt; {<br>    setTimeout(() =&gt; {<br>      resolve(&#39;Async Task 3 Completed&#39;);<br>    }, 2000);<br>  });<br>}<br><br>async function executeAsyncGenerator() {<br>  const gen = asyncGenerator();<br>  let result;<br>  while (true) {<br>    const { value, done } = await gen.next(result);<br>    if (done) {<br>      break;<br>    }<br>    result = await value;<br>  }<br>}<br><br>executeAsyncGenerator();</pre><h3>6) Typing Animations</h3><p>We all have used <em>Typing Animation, </em>a visual effect designed to mimic someone typing text.</p><p>Let’s see how we can leverage generators to achieve this.</p><pre>function* typeAnimation(text){<br>  for(let char of text){<br>    yield char;<br>  }<br>}<br><br>const itr = typeAnimation(&quot;Coding Beauty&quot;);<br>function typeAnimation(elementId){<br>  let element = document.getElementById(elementId);<br>  setInterval(()=&gt;{<br>    let result = itr.next();<br>    !result.done &amp;&amp; element.innerHTML += result.value;<br>  },100);<br><br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fHtfOMULHFfozRFa.gif" /></figure><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><h3>Stackademic 🎓</h3><p>Thank you for reading until the end. Before you go:</p><ul><li>Please consider <strong>clapping</strong> and <strong>following</strong> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><strong>X</strong></a><strong> | </strong><a href="https://www.linkedin.com/company/stackademic"><strong>LinkedIn</strong></a><strong> | </strong><a href="https://www.youtube.com/c/stackademic"><strong>YouTube</strong></a><strong> | </strong><a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a></li><li>Visit our other platforms: <a href="https://plainenglish.io/"><strong>In Plain English</strong></a><strong> | </strong><a href="https://cofeed.app/"><strong>CoFeed</strong></a><strong> | </strong><a href="https://venturemagazine.net/"><strong>Venture</strong></a><strong> | </strong><a href="https://blog.cubed.run/"><strong>Cubed</strong></a></li><li>More content at <a href="https://stackademic.com/"><strong>Stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8bc54d5a0bf0" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/mastering-javascript-generators-practical-use-cases-8bc54d5a0bf0">Mastering JavaScript Generators: Practical Use Cases</a> was originally published in <a href="https://blog.stackademic.com/">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Robust React Applications: A Guide to Applying SOLID Principles]]></title>
            <link>https://medium.com/@mayank2803sharma/building-robust-react-applications-a-guide-to-applying-solid-principles-486c9c27cdca?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/486c9c27cdca</guid>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[solid-principles]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Tue, 13 Feb 2024 21:01:45 GMT</pubDate>
            <atom:updated>2024-02-13T21:01:45.603Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>If you’ve dipped your toes into the world of software development, chances are you’ve encountered the term “SOLID principles.” But what exactly are they, and why should React developers care? In this article, we’ll break down SOLID principles in a way that’s easy to understand and explore how they can supercharge your React development journey.</blockquote><p>SOLID is an acronym, where each letter represents one out of five design principles that help make the code <strong>understandable</strong>, <strong>flexible</strong>, and <strong>maintainable.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FB8uEkcGaVvoo07SMqyvWQ.png" /><figcaption>SOLID principles</figcaption></figure><ul><li><strong>S</strong>ingle responsibility principle (SRP)</li><li><strong>O</strong>pen-closed principle (OCP)</li><li><strong>L</strong>iskov substitution principle (LSP)</li><li><strong>I</strong>nterface segregation principle (ISP)</li><li><strong>D</strong>ependency inversion principle (DIP)</li></ul><p>In this article, we’ll talk about the importance of each principle and see how we can apply the learnings from SOLID in React applications.</p><p>SOLID principles were initially meant for object-oriented languages like Java and C#, where classes and interfaces play a big role. But in JavaScript, especially in React, we don’t rely on these concepts as much.</p><p>The good news is SOLID principles aren’t tied to any specific language or programming style. Even in the more functional world of React, we can still apply these principles to write cleaner and more maintainable code.</p><h3>1. Single Responsibility Principle (SRP)</h3><blockquote>every class should have only one responsibility.</blockquote><p>In React, adhering to the Single Responsibility Principle (SRP) means ensuring each component has a <strong>clear and distinct purpose</strong>. By focusing on a <strong>single task</strong>, we can enhance the clarity and maintainability of our codebase.</p><p>Here’s how we can effectively implement SRP in our React applications:</p><ol><li><strong>Component Modularity:</strong> Keep your components small and focused on doing one thing well. This approach improves code <strong>readability</strong> and makes it easier to understand and maintain.</li><li><strong>Task Segregation:</strong> Avoid mixing unrelated tasks within a single component. For example, a component responsible for rendering a form should not also handle fetching data from an API. Separating concerns in this way improves code organization and reduces complexity.</li><li><strong>Composition: </strong>By breaking down complex UIs into smaller, reusable parts, we can build more modular and flexible applications. This approach also encourages code <strong>reusability</strong> and <strong>reduces duplication</strong>.</li></ol><p>Let’s Take an example of a code that does not follow SRP and then we’ll refactor it to follow SRP.</p><pre>import React, { useState, useEffect } from &quot;react&quot;;<br>import axios from &quot;axios&quot;;<br><br>const UserDetails = () =&gt; {<br> const [user, setUser] = useState(null);<br> const [isLoading, setIsLoading] = useState(true);<br><br> useEffect(() =&gt; {<br>   axios.get(&quot;https://.../userDetails/&quot;).then((res) =&gt; {<br>       setUser(res.data)<br>   }).catch(e =&gt; {<br>       console.error(&#39;Error fetching user details:&#39;, e.message);<br>   }).finally(() =&gt; {<br>       setIsLoading(false);<br>   })<br> }, [])<br><br> if (isLoading){<br>   return &lt;p&gt;Loading...&lt;/p&gt;<br> }<br><br> return (<br>   &lt;div&gt;<br>       &lt;h2&gt;User Details&lt;/h2&gt;<br>       &lt;p&gt;Name: {user.name}&lt;/p&gt;<br>       &lt;p&gt;Email: {user.email}&lt;/p&gt;<br>   &lt;/div&gt;<br> );<br>};<br><br>export default UserDetails;</pre><p>This code looks well-written right? At least this is what most of us are used to.</p><p>As we examine the UserDetails component, we start to notice a few issues. It&#39;s taking on multiple responsibilities:</p><ol><li>Managing the state.</li><li>Making requests for list items and handling the fetching process.</li><li>Rendering the component.</li></ol><p>While it may seem ordinary at first glance, according to the Single Responsibility Principle (SRP), it’s juggling more responsibilities than it should. So, how can we improve it?</p><p>One common approach is to extract logic that involves side effects, like fetching data, into a custom hook. By doing this, we can separate concerns and adhere to SRP more effectively.</p><p>Let’s create a custom hook</p><pre>import React, { useEffect, useState } from &quot;react&quot;;<br>import axios from &quot;axios&quot;;<br><br><br>const useFetchListItems = () =&gt; {<br>   const [user, setUser] = useState([]);<br>   const [isLoading, setIsLoading] = useState(true);<br><br>useEffect(() =&gt; {<br>   axios.get(&quot;https://.../listitems/&quot;).then((res) =&gt; {<br>       setUser(res.data)<br>   }).catch(e =&gt; {<br>       console.error(&#39;Error fetching user details:&#39;, e.message);<br>   }).finally(() =&gt; {<br>       setIsLoading(false);<br>   })<br> }, [])<br><br>   return { user, isLoading };<br>}</pre><p>After refactoring, our component becomes easier to understand. Its only job is to display information, which makes it more maintainable and flexible.</p><p>Here’s the refactored version of our component, aligned with the Single Responsibility Principle (SRP):</p><pre>import React from &quot;react&quot;;<br>import { useFetchUserDetails } from &quot;hooks/useFetchUserDetails&quot;;<br><br>const UserDetails = () =&gt; {<br> const { user, isLoading } = useFetchUserDetails();<br><br> if (isLoading){<br>   return &lt;p&gt;Loading...&lt;/p&gt;<br> }<br><br> return (<br>   &lt;div&gt;<br>       &lt;h2&gt;User Details&lt;/h2&gt;<br>       &lt;p&gt;Name: {user.name}&lt;/p&gt;<br>       &lt;p&gt;Email: {user.email}&lt;/p&gt;<br>   &lt;/div&gt;<br> );<br>};<br><br>export default UserDetails;</pre><p>Upon closer examination, our new hook is handling both state management and fetching list items. This violates the Single Responsibility Principle.<br>To address this, let’s separate the logic for fetching list items into its module.</p><p><strong>API File</strong></p><pre>import axios from &quot;axios&quot;;<br><br>export const fetchUserDetails = () =&gt; {<br> return axios<br>   .get(&quot;https://.../userDetails/&quot;)<br>   .catch((error) =&gt; {<br>     console.error(&#39;Error fetching user details:&#39;, error.message);<br>   })<br>   .then((response) =&gt; response.data);<br>};</pre><p><strong>Custom Hook File</strong></p><pre>import { useEffect, useState } from &quot;react&quot;;<br>import { fetchUserDetails } from &quot;./api&quot;;<br><br>const useFetchUserDetails = () =&gt; {<br> const [user, setUser] = useState(null);<br> const [isLoading, setIsLoading] = useState(true);<br><br> useEffect(() =&gt; {<br>   fetchUserDetails()<br>     .then((userData) =&gt; setUser(userData))<br>     .finally(() =&gt; setIsLoading(false));<br> }, []);<br><br> return { user, isLoading };<br>};</pre><p>Keeping it simple: While the Single Responsibility Principle (SRP) helps us maintain tidy, error-free code, it can also complicate our file structure and planning.<br>However, it’s important to find a balance. While SRP promotes clarity and maintenance, we shouldn’t overly complicate things. Sometimes, a bit of complexity is fine if it makes the code easier to understand overall.</p><h3>2. Open-closed principle (OCP)</h3><blockquote>software entities should be open for extension, but closed for modification</blockquote><p><strong>Open for extension: </strong>A component should allow for the addition of new behaviors, functionalities, and features without requiring modifications to its existing functionality.</p><p><strong>Closed for modification: O</strong>nce a React component has been created and implemented, it’s best to refrain from directly altering its source code unless absolutely necessary.</p><p>Let’s take an example to understand this</p><pre>import React from &#39;react&#39;;<br><br>const Button = ({ variant, children }) =&gt; {<br>  let buttonStyle = {};<br>  if (variant === &#39;primary&#39;) {<br>    buttonStyle = {<br>      backgroundColor: &#39;blue&#39;,<br>      color: &#39;white&#39;,<br>    };<br>  } else if (variant === &#39;secondary&#39;) {<br>    buttonStyle = {<br>      backgroundColor: &#39;white&#39;,<br>      color: &#39;black&#39;,<br>      border: &#39;1px solid black&#39;,<br>    };<br>  }<br><br>  return (<br>    &lt;button style={buttonStyle}&gt;<br>      {children}<br>    &lt;/button&gt;<br>  );<br>};<br><br>export default Button;</pre><p>Now, let’s say we want to add a new variant called “<strong>warning</strong>”, which should render a button with a yellow background and red text color.</p><p>The Above implementation of the Button component violates the <strong>OCP</strong> because we have to modify the component&#39;s source code to accommodate the new variant. This means the component is not closed for modification.</p><p>Let’s refactor this:-</p><pre>import React from &#39;react&#39;;<br><br>const Button = ({ variant, children, customStyles }) =&gt; {<br>  let buttonStyle = {};<br>  const baseStyles = {<br>    padding: &#39;8px 16px&#39;,<br>    borderRadius: &#39;4px&#39;,<br>    cursor: &#39;pointer&#39;,<br>  };<br><br>  switch (variant) {<br>    case &#39;primary&#39;:<br>      buttonStyle = {<br>        ...baseStyles,<br>        backgroundColor: &#39;blue&#39;,<br>        color: &#39;white&#39;,<br>      };<br>      break;<br>    case &#39;secondary&#39;:<br>      buttonStyle = {<br>        ...baseStyles,<br>        backgroundColor: &#39;white&#39;,<br>        color: &#39;black&#39;,<br>        border: &#39;1px solid black&#39;,<br>      };<br>      break;<br>    default:<br>      buttonStyle = baseStyles;<br>  }<br><br>  return (<br>    &lt;button style={{ ...buttonStyle, ...customStyles }}&gt;<br>      {children}<br>    &lt;/button&gt;<br>  );<br>};<br><br>export default Button;</pre><p>With this refactored approach, we’ve made the Button component open for extension. We can now add new variants without modifying the component&#39;s source code. <br>For example:</p><pre>&lt;Button variant=&quot;warning&quot; customStyles={{ backgroundColor: &#39;yellow&#39;, color: &#39;red&#39; }}&gt;Danger!&lt;/Button&gt;</pre><p>This way, the Button component is closed for modification but open for extension, adhering to the <strong>Open/Closed Principle</strong>.</p><h3>3. Liskov Substitution Principle (LSP)</h3><blockquote><em>Objects of a superclass should be replaceable with objects of its subclasses.</em></blockquote><p>In simpler terms, if you have a hierarchy of classes where one class inherits from another, you should be able to substitute instances of the child class wherever instances of the parent class are expected, and the program should still behave as intended.</p><p>In the context of React, applying <strong>LSP</strong> means that a child component should be able to replace its parent component without causing any unexpected behavior.</p><p>Let’s take an example:-</p><pre>const Button = ({ onClick, children }) =&gt; {<br>  return (<br>    &lt;button onClick={onClick}&gt;{children}&lt;/button&gt;<br>  );<br>};</pre><pre>const PrimaryButton = ({ children }) =&gt; {<br>  return (<br>    &lt;button style={{ backgroundColor: &#39;blue&#39;, color: &#39;white&#39; }}&gt;{children}&lt;/button&gt;<br>  );<br>};</pre><p>The PrimaryButton here is styled differently, but it doesn&#39;t accept or pass along the onClick prop, meaning it can&#39;t fully replace Button in all contexts where a button&#39;s click functionality is required.</p><p>Let’s Refactor it, so it follows LSP</p><pre>const PrimaryButton = ({ onClick, children }) =&gt; {<br>  return (<br>    &lt;button onClick={onClick} style={{ backgroundColor: &#39;blue&#39;, color: &#39;white&#39; }}&gt;<br>      {children}<br>    &lt;/button&gt;<br>  );<br>};</pre><p>Now, PrimaryButton can be used anywhere Button is used, adhering to <strong>LSP</strong>. It can handle clicks and display children just like Button, but with additional styling.</p><h3>4. Interface Segregation Principle (ISP)</h3><blockquote>No code should be forced to depend on methods it does not use.</blockquote><p>The Interface Segregation Principle (ISP) in React emphasizes that components should only depend on the props that they actually use.</p><p>Let’s explore this concept further with an example:</p><pre>const User = ({ item }) =&gt; {<br>  return (<br>    &lt;View&gt;<br>      &lt;h1&gt;{item.name}&lt;/h1&gt;<br>      &lt;Text&gt;{item.description}&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><p>In this example, the User component receives an item prop, which contains multiple fields, however, the component only needs name, and description from the item prop.</p><p>To adhere to the ISP, we should modify the User component to only accept the specific props it needs:</p><pre>const User = ({ name, description }) =&gt; {<br>  return (<br>    &lt;View&gt;<br>      &lt;h1&gt;{item.name}&lt;/h1&gt;<br>      &lt;Text&gt;{item.description}&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><p>By doing so, we ensure that the component is not dependent on props it doesn’t use, aligning with the principles of ISP.<br>This makes the component more focused, maintainable, and easier to reason about.</p><h3>5. Dependency Inversion Principle (DIP)</h3><blockquote>one should depend upon abstractions, not concretions</blockquote><p>In simple words, one component shouldn’t directly depend on another component, but rather they both should depend on some common abstraction.</p><p>Let’s take an example to understand this.</p><pre>const CreateListItemForm = () =&gt; {<br>  const handleCreateListItemForm = async (e) =&gt; {<br>    try {<br>      const formData = new FormData(e.currentTarget);<br>      await axios.post(&quot;https://myapi.com/listItems&quot;, formData);<br>    } catch (err) {<br>      console.error(err.message);<br>    }<br>  };<br><br>  return (<br>    &lt;form onSubmit={handleCreateListItemForm}&gt;<br>      &lt;input name=&quot;title&quot; /&gt;<br>      &lt;input name=&quot;description&quot; /&gt;<br>      &lt;input name=&quot;image&quot; /&gt;<br>    &lt;/form&gt;<br>  );<br>};</pre><p>In this example, the CreateListItemForm component directly handles the logic for creating a list item, including <strong>sending a POST request</strong> to an API endpoint. However, if we need another form for editing list items with similar UI but different logic, the CreateListItemForm would be unreusable.</p><p>Let’s refactor it:</p><pre>const ListItemForm = ({ onSubmit }) =&gt; {<br>  return (<br>    &lt;form onSubmit={onSubmit}&gt;<br>      &lt;input name=&quot;title&quot; /&gt;<br>      &lt;input name=&quot;description&quot; /&gt;<br>      &lt;input name=&quot;image&quot; /&gt;<br>    &lt;/form&gt;<br>  );<br>};</pre><p>Now, we’ve created a generic ListItemForm component that only focuses on rendering the form UI and calls the onSubmit function provided via props when the form is submitted. This component is <strong>agnostic </strong>to the specific logic for <em>creating </em>or <em>editing </em>list items.</p><pre>const CreateListItemForm = () =&gt; {<br>  const handleCreateListItem = async (e) =&gt; {<br>    try {<br>      const formData = new FormData(e.currentTarget);<br>      await axios.post(&quot;https://myapi.com/listItems&quot;, formData);<br>    } catch (err) {<br>      console.error(err.message);<br>    }<br>  };<br><br>  return &lt;ListItemForm onSubmit={handleCreateListItem} /&gt;;<br>};<br><br>const EditListItemForm = () =&gt; {<br>  const handleEditListItem = async (e) =&gt; {<br>    try {<br>      // Editing logic<br>    } catch (err) {<br>      console.error(err.message);<br>    }<br>  };<br><br>  return &lt;ListItemForm onSubmit={handleEditListItem} /&gt;;<br>};</pre><p>By following these <strong>SOLID principles</strong>, we can create <strong>robust </strong>and <strong>maintainable </strong>React applications that are <strong>easy to understand</strong> and <strong>modify</strong>. Remember, a little bit of upfront design can save a lot of headaches down the line. <br>Happy coding!</p><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=486c9c27cdca" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Demystifying Vercel: How It Works and How to Create Vercel]]></title>
            <link>https://medium.com/@mayank2803sharma/demystifying-vercel-how-it-works-and-how-to-create-vercel-763586070478?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/763586070478</guid>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[mern-stack]]></category>
            <category><![CDATA[vercel]]></category>
            <category><![CDATA[backend]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Sun, 11 Feb 2024 20:13:15 GMT</pubDate>
            <atom:updated>2024-02-11T20:13:15.182Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/572/1*tUamZdhNRj2LZT1xYCQ0AQ.png" /><figcaption>Vercel Image</figcaption></figure><h3><strong>Introduction:</strong></h3><p>In the world of web development, efficiency and speed are paramount. Developers constantly seek tools that streamline the deployment process while maintaining performance and reliability.</p><p><strong>What is Vercel?</strong></p><p>Vercel is a cloud platform designed to simplify the deployment process for web applications, particularly those built with modern frameworks like React, Next, etc.<br>It lets you <strong>deploy their front end stupidly easily.</strong></p><p>Beyond the <strong>frontend-as-a-service</strong> offering, Vercel has consistently released features to make it a one-stop solution to build your entire application:</p><ol><li><strong>Edge Functions:- </strong>let you write backend code serverless to handle things like authentication etc.</li><li><strong>Analytics:- </strong>statistics and dashboards on your site’s performance and accessibility.</li><li><strong>CLI / API:- </strong>interact programmatically with Vercel to run deployments, performance checks, etc.</li></ol><p>Vercel operates on <strong>serverless architecture</strong> combined with a global <strong>content delivery network</strong> (CDN).</p><h3>How Does Vercel Work on a High Level:</h3><p>Deploying a website on Vercel typically follows a <strong>three-stage process</strong> at a high level:</p><ol><li>Uploading the Project Files.</li><li>Creating the Deployment.</li><li>Request Phase.</li></ol><p><strong>Uploading the Project Files:-</strong></p><p>A POST request is made containing the project’s files to be uploaded to a scalable, secure, and highly durable data storage service.<br>In simple words, it takes the files from your GitHub Repository and then uploads them to something like <strong>AWS S3</strong>.</p><p><strong>Creating the deployment:-</strong></p><p>Once the files have been uploaded successfully to the storage service, another POST request is made to start the build and deployment process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/1*HYcuP_UiOZq38aw7LZO31A.png" /><figcaption>Deployment Phase</figcaption></figure><p>Here’s a breakdown of the deployment process on Vercel:</p><ol><li><strong>Authentication and Validation:</strong> Vercel authenticates the user and checks the request’s authenticity and permissions against the vercel.json file to prevent unauthorized access.</li><li><strong>Scheduling Build:</strong> If everything checks out, the deployment is scheduled for building.</li><li><strong>Tracking Build Progress:</strong> While processing files, the build container pings an API endpoint to track deployment status, visible in the CLI and dashboard.</li><li><strong>Ready for CDN:</strong> Once resources are provisioned and metadata is uploaded, the deployment is ready to be served via the Vercel CDN</li></ol><p>In Simple words and keeping all the complex things as a black box, the Deployment Service grabs the repository code from the Storage location (like S3) and then builds that project and stores the build in the Storage.</p><p><strong>Request Phase:-</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/971/1*A0PyROwlWP_SWDMFs6Lggw.png" /><figcaption>CDN(Requesting website)</figcaption></figure><p>After deployment, you receive a URL for your website, such as myapp.vercel.app which you can use to access it.</p><p>Let’s delve into how Vercel accomplishes this behind the scenes:</p><ol><li><strong>DNS Lookup:</strong> When you type a website’s address, Vercel uses smart routing to make sure your request reaches the closest data center, which makes the website load faster.</li><li><strong>Content Serving:</strong> Different types of content like static pages, special functions, or optimized images are served accordingly.</li><li><strong>Caching: </strong>Vercel caches some of the stuff it sends you, so the next time you ask for it, it can give it to you faster.</li></ol><p><strong>Services Vercel uses:-</strong></p><ol><li>Amazon S3</li><li>Amazon Simple Queue Service</li><li>Auto-scaling fleet of EC2 instances powered by AWS Fargate</li><li>Amazon Global Accelerator</li><li>AWS Global Network</li><li>Amazon EKS</li><li>AWS Lambda</li></ol><p>Wasn’t it fascinating to learn how Vercel operates behind the scenes? <br>Now, let’s move on to the second part of our blog, where we’ll embark on <strong>building </strong>something similar to <strong>Vercel</strong>.</p><h3>Crafting Your Vercel</h3><p><strong>Disclaimer:- </strong>Our aim is to create a simplified version of Vercel, enabling the deployment of React projects. While prioritizing learning, we’ll initially overlook considerations like security, scalability, practices, and performance. These aspects may be addressed in future iterations or separate blog posts.</p><p>Similar to Vercel’s three-stage process, we’ll divide our <strong>project </strong>into three parts:</p><ol><li>Upload Service</li><li>Deploy Service</li><li>Request Service</li></ol><p><strong>System Design</strong></p><p>Let’s dive inside the <strong>System Design</strong> of how our project works:</p><ol><li><strong>Upload Service</strong></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/985/1*0FXOyBEZa8fHrlpRSTjldA.png" /><figcaption>Upload Service Diagram</figcaption></figure><p>From the client side, the Upload Server receives the URL of the GitHub repository. This URL is utilized to clone the project from GitHub. Once the project is successfully cloned into the system, the server generates a unique ID and uploads the project to <strong>AWS S3</strong> using that ID. Subsequently, the server stores this ID in a <strong>queue</strong>, which will facilitate the Deploy Server. For the queue, options such as <strong>Redis </strong>or <strong>AWS SQS</strong> can be employed. Finally, the server sends back the ID to the client.</p><p><strong>2. Deploying Service</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mYJb2i-1VrPJ4rH52eDdpA.png" /><figcaption>Deploy Service Diagram</figcaption></figure><p>From the queue, the Deploy Server retrieves an ID and proceeds to clone the project stored in S3 (Object Storage). Once the project is cloned, the server executes npm install and npm run build to build the project. Following this, the server stores dist (build of the project) on S3.</p><p>The number of servers deployed — whether one, two, or more — depends on the quantity of IDs received from the queue. This scalability can be achieved using auto-scaling mechanisms like <strong>AWS Fargate</strong>.</p><p>3. <strong>Request Phase</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NbrVufbOBZ9UUKUTQwxzIQ.png" /><figcaption>Request Phase</figcaption></figure><p>After the deployment phase, users can access their website by visiting dist&lt;id&gt;.vercel.app/index.html</p><p>When a user sends a request to the server, the server retrieves the build from S3 using the&lt;id&gt;and serves it back to the user. This build typically includes HTML, CSS, JavaScript, and other necessary files.</p><p>This concludes the high-level system design overview of our project’s functionality.<br>Now, let’s delve deeper and begin writing the code to bring this project to life.</p><h3>Code: Let’s roll up our sleeves and dive in!</h3><p>To facilitate the entire functionality, we will employ three servers, each handling one of the three services.</p><p>Let’s start with the upload server.</p><h3>Upload Server</h3><p>At a high level, the Upload Server is responsible for receiving the GitHub repository URL from the client side, cloning the repository onto the system, and then uploading it to cloud storage.<br>For this project, we’ve decided to use <strong>Cloudflare R2</strong> instead of <strong>AWS S3</strong>, as it offers similar functionality, and Cloudflare provides a <strong>free tier</strong> for R2, making it an excellent choice for our needs. Additionally, we’ll utilize an <strong>AWS SDK</strong> for compatibility with Cloudflare R2.</p><p>Now, let’s discuss the required tech stack and dependencies to get started with the coding process:-</p><ol><li>Node.js</li><li>TypeScript</li><li>Redis(for queue part)</li><li>NPM Packages:- express, redis, aws-sdk, simple-git, cors, dotenv</li><li>Cloudflare</li></ol><p>Create a typescript project and do basic configuration like</p><ol><li>Change rootDir to src</li><li>Change outDir to dist</li></ol><p>This is how the directory structure will look like</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/313/1*7c1w7XLadJhzFkesRGKe4Q.png" /><figcaption>Directory of Upload Server</figcaption></figure><p><strong>Index.ts</strong></p><pre>import express from &quot;express&quot;;<br>import cors from &quot;cors&quot;;<br>import simpleGit from &quot;simple-git&quot;;<br>import { generate } from &quot;./utils&quot;;<br>import { getAllFiles } from &quot;./file&quot;;<br>import path from &quot;path&quot;;<br>import { uploadFile } from &quot;./aws&quot;;<br>import { createClient } from &quot;redis&quot;;<br><br>const publisher = createClient(); // to store id in the queue<br>publisher.connect();<br><br>const subscriber = createClient(); // to store about the status being uploaded or deployed<br>subscriber.connect();<br><br>const app = express();<br>app.use(cors());<br>app.use(express.json());<br><br>app.post(&quot;/deploy&quot;, async (req, res) =&gt; {<br>  const repoUrl = req.body.repoUrl;<br>  const id = generate(); // something like asd12<br>  await simpleGit().clone(repoUrl, path.join(__dirname, `output/${id}`)); // clones the repo in dist/output<br><br>  const files = getAllFiles(path.join(__dirname, `output/${id}`));<br><br>  files.forEach(async (file) =&gt; {<br>    const filename = path.relative(__dirname, file).replace(/\\/g, &quot;/&quot;);<br>    await uploadFile(filename, file); // upload all the files to the R2 bucket<br>  });<br><br>  await new Promise((resolve) =&gt; setTimeout(resolve, 5000)); // waiting for 5 seconds so that id does not get stored in the queue<br>  // before the code gets deployed to R2<br><br>  publisher.lPush(&quot;build-queue&quot;, id);  // store the id in the queue shared by upload service and deploy service<br>  publisher.hSet(&quot;status&quot;, id, &quot;uploaded&quot;); // store the status in redis regarding project being uploaded or deployed<br><br>  res.json({<br>    id: id,<br>  });<br>});<br><br>app.get(&quot;/status&quot;, async (req, res) =&gt; {  // api to get the status of the project<br>  const id = req.query.id;<br>  const response = await subscriber.hGet(&quot;status&quot;, id as string);<br>  res.json({<br>    status: response,<br>  });<br>});<br><br>app.listen(3000);</pre><p><strong>What does this code do:- </strong><br>When the <strong>/deploy API</strong> is accessed, the first step is to extract the GitHub URL from the request body. Subsequently, we generate a random ID using a generate function. Following this, we clone the project from GitHub using simpleGit and store it in <strong>dist/output/&lt;id&gt;</strong>.</p><p>Next, we create an array containing the paths of all the files in that repository. We then iterate over this array and store each file of the repository in <strong>Cloudflare R2</strong>, structured under <strong>output/&lt;id&gt;/&lt;files&gt;</strong>.</p><p>After this, we store the ID in the <strong>Redis queue</strong>, which will be consumed by the next service. Additionally, we store the status of that project as “uploaded” in a Redis set. Finally, we return the user ID as a response.</p><p><strong>aws.ts</strong></p><pre>require(&quot;dotenv&quot;).config();<br>import { S3 } from &quot;aws-sdk&quot;;<br>import fs from &quot;fs&quot;;<br><br>const s3 = new S3({<br>  endpoint: process.env.ENDPOINT,<br>  accessKeyId: process.env.ACCESSKEYID,<br>  secretAccessKey: process.env.SECRETACCESSKEY,<br>});<br><br>export const uploadFile = async (fileName: string, localFilePath: string) =&gt; {<br>  const fileContent = fs.readFileSync(localFilePath);<br>  const response = await s3<br>    .upload({<br>      Body: fileContent,<br>      Bucket: &quot;vercel&quot;,<br>      Key: fileName,<br>    })<br>    .promise();<br>  console.log(response);<br>};</pre><p><strong>file.ts</strong></p><pre>import fs from &quot;fs&quot;;<br>import path from &quot;path&quot;;<br><br>export const getAllFiles = (folderPath: string) =&gt; {<br>  let response: string[] = [];<br><br>  const allFilesAndFolders = fs.readdirSync(folderPath);<br>  allFilesAndFolders.forEach((file) =&gt; {<br>    const fullFilePath = path.join(folderPath, file);<br>    if (fs.statSync(fullFilePath).isDirectory()) {<br>      response = response.concat(getAllFiles(fullFilePath));<br>    } else {<br>      response.push(fullFilePath);<br>    }<br>  });<br>  return response;<br>};</pre><p><strong>utils.ts</strong></p><pre>const MAX_LEN = 5;<br><br>export function generate() {<br>  let ans = &quot;&quot;;<br>  const subset = &quot;123456789qwertyuiopasdfghjklzxcvbnm&quot;;<br>  for (let i = 0; i &lt; MAX_LEN; i++) {<br>    ans += subset[Math.floor(Math.random() * subset.length)];<br>  }<br>  return ans;<br>}</pre><p><strong>.env</strong></p><pre>ENDPOINT = &quot;cloudflare R2 end point&quot;<br>ACCESSKEYID = &quot;&quot;<br>SECRETACCESSKEY = &quot;&quot;</pre><p>Now, let’s delve into how the Deploy Server operates.</p><h3><strong>Deploy Server</strong></h3><p>In the Deploy Server, an infinite loop is initiated to continuously monitor the presence of an ID in the Redis queue. When an ID is detected, it is dequeued, and the deployment process begins.</p><p>Initially, the project associated with that ID is downloaded from our R2 Bucket. Subsequently, the project is built, which typically involves running npm install followed by npm run build.</p><p>Once the build process is completed, the generated dist the directory in that project is stored back in the R2 bucket, utilizing dist/&lt;id&gt; as the path.</p><p>After successfully storing the build in the bucket, the status in the Redis set is updated from “uploaded” to “deployed”.</p><p>Now, let’s discuss about dependencies to get started with this:-</p><ol><li>install npm packages:- aws-sdk, dotenv, redis</li></ol><p>Create a typescript project and do basic configuration like</p><ol><li>Change rootDir to src</li><li>Change outDir to dist</li></ol><p>This is how the directory structure will look like</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/315/1*u8ZUSPvBAwCPd9s45mc1bA.png" /><figcaption>Directory of Deploy Server</figcaption></figure><p><strong>index.ts</strong></p><pre>import { createClient, commandOptions } from &quot;redis&quot;;<br>import { copyFinalDist, downloadS3Folder } from &quot;./aws&quot;;<br>import { buildProject } from &quot;./utils&quot;;<br>const subscriber = createClient();  // to get the id from the redis-queue<br>subscriber.connect();<br><br>const publisher = createClient(); // to change the status to deployed<br>publisher.connect();<br><br>async function main() {<br>  while (1) {<br>    const res = await subscriber.brPop( //checks if there is any id in queue or not<br>      commandOptions({ isolated: true }),<br>      &quot;build-queue&quot;,<br>      0<br>    );<br>    const id = res.element;<br><br>    await downloadS3Folder(`output/${id}`); // download the project<br>    await buildProject(id); // build the project<br>    copyFinalDist(id);  // copy it back to the R2 bucket<br>    publisher.hSet(&quot;status&quot;, id, &quot;deployed&quot;); // sets the status as deployed<br>  }<br>}<br>main();</pre><p><strong>utils.ts</strong></p><pre>import { exec, spawn } from &quot;child_process&quot;;<br>import path from &quot;path&quot;;<br><br>export function buildProject(id: string) {<br>  return new Promise((resolve) =&gt; {<br>    const child = exec(<br>      `cd ${path.join(<br>        __dirname,<br>        `output/${id}`<br>      )} &amp;&amp; npm install &amp;&amp; npm run build`<br>    );<br><br>    child.stdout?.on(&quot;data&quot;, function (data) {<br>      console.log(&quot;stdout: &quot; + data);<br>    });<br>    child.stderr?.on(&quot;data&quot;, function (data) {<br>      console.log(&quot;stderr: &quot; + data);<br>    });<br><br>    child.on(&quot;close&quot;, function (code) {<br>      resolve(&quot;&quot;);<br>    });<br>  });<br>}</pre><p>We utilize the exec method to instantiate a child process within the current server environment. This process navigates to the directory dist/output/&lt;id&gt;, where it sequentially executes npm install to install all project dependencies. Following this, the command npm run build is executed to generate a build directory named dist within the repository. Given the asynchronous nature of these tasks, we employ a promise to await their completion before advancing to the next steps.</p><p><strong>aws.ts</strong></p><pre>import { S3 } from &quot;aws-sdk&quot;;<br>import fs from &quot;fs&quot;;<br>import path from &quot;path&quot;;<br>require(&quot;dotenv&quot;).config();<br>const s3 = new S3({<br>  endpoint: process.env.ENDPOINT,<br>  accessKeyId: process.env.ACCESSKEYID,<br>  secretAccessKey: process.env.SECRETACCESSKEY,<br>});<br><br>// output/asdasd<br>// to download all the files from R2 bucket to server in the dist/output/&lt;id&gt;<br>export async function downloadS3Folder(prefix: string) {<br>  const allFiles = await s3<br>    .listObjectsV2({<br>      Bucket: &quot;vercel&quot;,<br>      Prefix: prefix,<br>    })<br>    .promise();<br><br>  //<br>  const allPromises =<br>    allFiles.Contents?.map(async ({ Key }) =&gt; {<br>      return new Promise(async (resolve) =&gt; {<br>        if (!Key) {<br>          resolve(&quot;&quot;);<br>          return;<br>        }<br>        const finalOutputPath = path.join(__dirname, Key);<br>        const outputFile = fs.createWriteStream(finalOutputPath);<br>        const dirName = path.dirname(finalOutputPath);<br>        if (!fs.existsSync(dirName)) {<br>          fs.mkdirSync(dirName, { recursive: true });<br>        }<br>        s3.getObject({<br>          Bucket: &quot;vercel&quot;,<br>          Key,<br>        })<br>          .createReadStream()<br>          .pipe(outputFile)<br>          .on(&quot;finish&quot;, () =&gt; {<br>            resolve(&quot;&quot;);<br>          });<br>      });<br>    }) || [];<br>  console.log(&quot;awaiting&quot;);<br><br>  await Promise.all(allPromises?.filter((x) =&gt; x !== undefined));<br>}<br>// to store the build in R2 bucket<br>export function copyFinalDist(id: string) {<br>  const folderPath = path.join(__dirname, `output/${id}/dist`);<br>  const allFiles = getAllFiles(folderPath);<br>  allFiles.forEach((file) =&gt; {<br>    uploadFile(<br>      (`dist/${id}/` + file.slice(folderPath.length + 1)).replace(/\\/g, &quot;/&quot;),<br>      file<br>    );<br>  });<br>}<br>// this function generates an array of path all the files in the folder<br>const getAllFiles = (folderPath: string) =&gt; {<br>  let response: string[] = [];<br><br>  const allFilesAndFolders = fs.readdirSync(folderPath);<br>  allFilesAndFolders.forEach((file) =&gt; {<br>    const fullFilePath = path.join(folderPath, file);<br>    if (fs.statSync(fullFilePath).isDirectory()) {<br>      response = response.concat(getAllFiles(fullFilePath));<br>    } else {<br>      response.push(fullFilePath);<br>    }<br>  });<br>  return response;<br>};<br>// used to upload the files to R2<br>const uploadFile = async (fileName: string, localFilePath: string) =&gt; {<br>  const fileContent = fs.readFileSync(localFilePath);<br>  const response = await s3<br>    .upload({<br>      Body: fileContent,<br>      Bucket: &quot;vercel&quot;,<br>      Key: fileName,<br>    })<br>    .promise();<br>  console.log(response);<br>};</pre><p><strong>.env</strong></p><pre>ENDPOINT = &quot;cloudflare R2 end point&quot;<br>ACCESSKEYID = &quot;&quot;<br>SECRETACCESSKEY = &quot;&quot;</pre><p>Let’s talk about the last phase which is the request phase.</p><h3>Request Phase:-</h3><p>In the final phase, when a user sends a request to the server with the ID of the deployed project, the server retrieves the build from the R2 bucket and serves it to the user. The build, represented by the dist folder, primarily comprises HTML, CSS, and JavaScript files. These files are essential for rendering the website in the user&#39;s browser, as browsers inherently comprehend HTML, CSS, and JavaScript. <br>While higher-level frameworks like React are used in development, they are ultimately translated into JavaScript code that browsers can process for rendering.</p><p>Now, let’s discuss about dependencies to get started with this:-</p><ol><li>install npm packages:- aws-sdk, dotenv, express</li></ol><p>Create a typescript project and do basic configuration like</p><ol><li>Change rootDir to src</li><li>Change outDir to dist</li></ol><p>This is how the directory structure will look like</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/322/1*A8Xg17PemUexf8CDvtehiQ.png" /><figcaption>Request Server Directory</figcaption></figure><p><strong>index.ts</strong></p><pre>require(&quot;dotenv&quot;).config();<br>import express from &quot;express&quot;;<br>import { S3 } from &quot;aws-sdk&quot;;<br><br>const s3 = new S3({<br>  endpoint: process.env.ENDPOINT,<br>  accessKeyId: process.env.ACCESSKEYID,<br>  secretAccessKey: process.env.SECRETACCESSKEY,<br>});<br><br>const app = express();<br><br>app.get(&quot;/*&quot;, async (req, res) =&gt; {  //  global route catch<br><br>  const host = req.hostname;<br>  const id = host.split(&quot;.&quot;)[0];<br>  const filePath = req.path;<br>  const contents = await s3<br>    .getObject({<br>      Bucket: &quot;vercel&quot;,<br>      Key: `dist/${id}${filePath}`,<br>    })<br>    .promise();<br><br>  const type = filePath.endsWith(&quot;html&quot;)<br>    ? &quot;text/html&quot;<br>    : filePath.endsWith(&quot;css&quot;)<br>    ? &quot;text/css&quot;<br>    : &quot;application/javascript&quot;;<br>  res.set(&quot;Content-Type&quot;, type);<br>    console.log(type);<br>  res.send(contents.Body);<br>});<br><br>app.listen(3001);</pre><p>In this phase, the server retrieves the project’s ID, fetches the corresponding content from the R2 bucket, and then serves it to the user.</p><p><strong>Now, the question arises: how do I test this on a local host environment?</strong></p><p>While uploading and deploying are relatively straightforward tasks, verifying the website poses a challenge. Let’s consider an example URL format:</p><p><strong>&lt;id&gt;.vercelclone.com:3001/index.html</strong> <br>For instance:- if the ID is “epwic”, the URL would be <strong>epwic.vercelclone.com:3001/index.html</strong></p><p>To achieve local testing, we can mimic this URL format by renaming <strong>localhost </strong>to <strong>epwic.vercelclone.com (</strong>or whatever is your id.vercelclone.com<strong>).</strong></p><p><strong>MAC</strong></p><p>If you are using Mac it’s going to be a piece of cake for you.</p><ol><li>Open Terminal and write this command.</li></ol><pre>sudo vi /etc/hosts</pre><p>2. Write the following thing</p><pre>127.0.0.1  epwic/vercelclone.com</pre><p>In this scenario, “epwic” represents the unique ID of my project. Similarly, in your case, you would have a different ID specific to your project.</p><p><strong>Windows</strong></p><p>In Windows, renaming localhost is kind of complex, so we are going to test it in another way.</p><p>In your index.ts code of <strong>Request phase</strong>, do these changes</p><pre>app.get(&quot;/*&quot;, async (req, res) =&gt; {<br><br>  const id = &quot;ka8u3&quot;;<br>  const filePath = req.path;<br>  const contents = await s3<br>    .getObject({<br>      Bucket: &quot;vercel&quot;,<br>      Key: `dist/${id}${filePath}`,<br>    })<br>    .promise();</pre><p>Here we are manually writing down the id.<br>The URL is going to be:- <a href="http://localhost:3001/index.html"><strong>http://localhost:3001/index.html</strong></a></p><p>Thanks a lot for reading the entire blog and congrats you now know how Vercel works and how you can create one for yourself.</p><p>I’m aware that the code for this project isn’t production-ready and may not adhere to best practices. The primary aim of this blog was to provide an understanding of how Vercel works and how one can create a basic clone of it. If the response to this blog is positive, I’ll consider developing a Vercel clone with production-level code, implementing best practices, and ensuring scalability and security.</p><p>Here is a video of how it works:-</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FgzJpwnrbIXI%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DgzJpwnrbIXI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FgzJpwnrbIXI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d8a2e7d07843473a6ea7a77e57391035/href">https://medium.com/media/d8a2e7d07843473a6ea7a77e57391035/href</a></iframe><p>In case you want the code:-</p><ol><li><strong>Vercel Upload Service</strong>:- <a href="https://github.com/Mayank2808sharma/vercel-uploadService">https://github.com/Mayank2808sharma/vercel-uploadService</a></li><li><strong>Vercel Deploy Service:- </strong><a href="https://github.com/Mayank2808sharma/vercel-deployservice">https://github.com/Mayank2808sharma/vercel-deployservice</a></li><li><strong>Vercel Request Handler:- </strong><a href="https://github.com/Mayank2808sharma/vercel-requesthandler">https://github.com/Mayank2808sharma/vercel-requesthandler</a></li></ol><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=763586070478" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Query vs useEffect: Understanding the Differences]]></title>
            <link>https://medium.com/@mayank2803sharma/react-query-vs-useeffect-understanding-the-differences-d7ad480a0bab?source=rss-9e0b2306ad9b------2</link>
            <guid isPermaLink="false">https://medium.com/p/d7ad480a0bab</guid>
            <category><![CDATA[react-query]]></category>
            <category><![CDATA[useeffect]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[usemutation]]></category>
            <category><![CDATA[usequery]]></category>
            <dc:creator><![CDATA[Mayank sharma]]></dc:creator>
            <pubDate>Sat, 10 Feb 2024 05:51:21 GMT</pubDate>
            <atom:updated>2024-02-10T05:51:21.361Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/740/0*_f4ghHcUu0A_yuI4.png" /><figcaption>React Query Vs UseEffect</figcaption></figure><p>When building a react application, we often need to fetch data from APIs.</p><p>There are mainly two ways to achieve this:- <strong>useEffect </strong>and <strong>React Query.</strong></p><p>Now the question is which one to use?</p><p>Let&#39;s compare <strong>useEffect</strong> and <strong>React Query</strong> for fetching data and decide which one to in which case.</p><h3>Using useEffect to fetch data</h3><p>UseEffect has been a quick go-to way to fetch data for a long time.</p><p><em>Here is an example:-</em></p><pre>const MyComponent = () =&gt; {<br>  <br>const [data, setData] = useState(null);<br>  // State to manage loading state<br>  const [loading, setLoading] = useState(true);<br>  // State to handle error<br>  const [error, setError] = useState(null);<br><br>  useEffect(() =&gt; {<br>    // Function to fetch data<br>    const fetchData = async () =&gt; {<br>      try {<br>      <br>        setLoading(true);<br>        // Fetch data from an API<br>        const response = await fetch(&#39;https://api.example.com/data&#39;);<br>        // Parse the JSON response<br>        const responseData = await response.json();<br>        // Set the fetched data in state<br>        setData(responseData);<br>        // Set loading state to false after data is fetched<br>        setLoading(false);<br>      } catch (error) {<br>        // Set error state if there&#39;s an error during fetching<br>        setError(error.message);<br>        // Set loading state to false in case of error<br>        setLoading(false);<br>      }<br>    };<br>    fetchData()<br>    }, []);</pre><h3>When to Use:</h3><ol><li><strong>Simple Data Fetching:- </strong>If your application requires fetching data from an API once, useEffect is a good solution.</li><li><strong>Basic State Management: </strong>For applications with basic state management, where you handle data loading, error, etc manually.</li></ol><h3>Drawbacks of useEffect:</h3><ol><li>No built-in caching, pagination, or query invalidation support.</li><li>Loading, Error state has to be handled manually.</li></ol><h3>Using React Query to fetch data</h3><p>React Query is a library that handles fetching, caching, synchronizing, and updating state.</p><p><em>Here is an Example:-</em></p><pre>import { useQuery } from &#39;react-query&#39;;<br><br>const fetchUsers = async () =&gt; {<br>  const response = await fetch(&#39;https://jsonplaceholder.typicode.com/users&#39;);<br>  const data = await response.json();<br>  return data;<br>};<br><br>const UsersList = () =&gt; {<br>  const { data, isLoading, isError } = useQuery(&#39;users&#39;, fetchUsers);<br><br>  if (isLoading) {<br>    return &lt;div&gt;Loading...&lt;/div&gt;;<br>  }<br><br>  if (isError) {<br>    return &lt;div&gt;Error: Failed to fetch users&lt;/div&gt;;<br>  }<br><br>  return (<br>    &lt;div&gt;<br>      &lt;h2&gt;Users&lt;/h2&gt;<br>      &lt;ul&gt;<br>        {data.map(user =&gt; (<br>          &lt;li key={user.id}&gt;{user.name}&lt;/li&gt;<br>        ))}<br>      &lt;/ul&gt;<br>    &lt;/div&gt;<br>  );<br>};</pre><h3>When to Use:</h3><ol><li><strong>Complex Data Requirements:</strong> If your application requires features like caching, pagination, background data synchronization, or automatic query invalidation, React Query is the go-to way for you.</li><li><strong>Streamlined State Management: </strong>simplifies data fetching by automatically managing isLoading and isError states internally.</li><li><strong>Optimistic Updates: </strong>React Query smoothly manages to update the user interface (UI) optimistically, meaning it changes what you see on the screen right away, assuming that a change or action will succeed, even before getting confirmation.</li></ol><h3>Advantages:-</h3><ol><li><strong>Automatic Caching: </strong>provides automatic caching, reducing unnecessary network requests and improving performance.</li><li><strong>Pagination and Infinite Loading: </strong>Easily implement pagination and infinite loading with built-in features, simplifying complex UI requirements.</li><li><strong>Automatic Data Re-fetching:</strong> Automatically updates fetched data when changes occur, ensuring that the UI reflects the latest information without manual intervention.</li></ol><p>In summary, the choice between React Query and useEffect depends on the complexity of your data fetching requirements.</p><p>For simple applications with basic data fetching needs and limited states, useEffect provides a straightforward solution</p><p>for most real-world cases — especially when sharing and refetching data across components — React Query will save you time and headaches.</p><p>In case you want to connect with me:-</p><p><a href="https://twitter.com/mayanksharmaa03"><strong>Twitter(X)</strong></a><strong><br></strong><a href="https://www.linkedin.com/in/mayanksharma2808/"><strong>LinkedIn</strong></a><strong><br></strong><a href="https://github.com/Mayank2808sharma"><strong>Github</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d7ad480a0bab" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>