<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Lucas Lachance</title>
    <description>The latest articles on Forem by Lucas Lachance (@eslachance).</description>
    <link>https://forem.com/eslachance</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F554989%2Ff6064b65-ea70-4741-84a9-c059ef1dcbe3.jpg</url>
      <title>Forem: Lucas Lachance</title>
      <link>https://forem.com/eslachance</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eslachance"/>
    <language>en</language>
    <item>
      <title>MERN is not your god</title>
      <dc:creator>Lucas Lachance</dc:creator>
      <pubDate>Mon, 07 Apr 2025 16:45:19 +0000</pubDate>
      <link>https://forem.com/eslachance/mern-is-not-your-god-2ggi</link>
      <guid>https://forem.com/eslachance/mern-is-not-your-god-2ggi</guid>
      <description>&lt;p&gt;This article addresses a very specific conversation that I find myself having repeatedly with beginners who were suggested that they should learn web development in the MERN stack. &lt;/p&gt;

&lt;p&gt;I want to address it because there's a very real dumb reason why MERN is such a common suggestion, and why I'm sort of angry about it: it's because you can say MERN out loud, and remember it written, since it looks like a &lt;em&gt;word&lt;/em&gt; more than any other common tech stack.&lt;/p&gt;

&lt;p&gt;We humans, we love our acronyms, we love to make them sound like words, and we have generally lost the ability to generalize the full stack technologies by shoving it in the MERN acronym which is often literally used, not metaphorically. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Meaning of MERN
&lt;/h2&gt;

&lt;p&gt;Let's first explore what MERN actually means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;M stands for MongoDB, a document database that was very popular when the acronym was coined.&lt;/li&gt;
&lt;li&gt;E is for Express, which for decades was the defacto HTTP server library you wanted to use in node.&lt;/li&gt;
&lt;li&gt;R is React, the most popular front-end client-side rendering, one used by the industry, and still very relevant. &lt;/li&gt;
&lt;li&gt;N doesn't even relate to a specific part of the stack but rather just "node". &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that the stack is really just "mongo + express + react", which is not a &lt;em&gt;bad&lt;/em&gt; stack per-se. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Alternatives
&lt;/h2&gt;

&lt;p&gt;My point, though, is that it's just one single variation out of so many possibilities. So for each of those 4 parts, let's first explore just specific changes we can make.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mongo can be about 2 dozen different databases depending on your needs. MySQL, Postgres, Oracle, SQLite, etc. Not to mention hosted/distributed systems like Firestore, Cloudflare and AWS offerings.&lt;/li&gt;
&lt;li&gt;Express has much better, more modern, more solid alternatives. Fastify first of all, but also more specific depending on your needs. Hono, Nest, Koa, strapi, etc.&lt;/li&gt;
&lt;li&gt;React also has alternatives like Vue, SolidJS, Angular, Svelte and a slew of other more minor libraries.&lt;/li&gt;
&lt;li&gt;Even Node has alternatives: Deno and Bun, for example, are well known, and Bun also includes its own http server and build tools, and it's more performant. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But does anyone want to remember PFSD (Postgres, Fastify, Svelte, Deno), or ONVB (Oracle, Nest, Vue, Bun)? What about SSSN (SQLite, Strapi, Solid, Node), why is that not valid? &lt;/p&gt;

&lt;p&gt;My point here is that there are &lt;em&gt;hundreds&lt;/em&gt; of possible combinations of all of these alternatives, all equally valid, all equally potentially useful for your project, or appropriate for your needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  The not-even-acronyms
&lt;/h2&gt;

&lt;p&gt;Now, what about not even doing this as a completely separate stack, but an actually integrated solution that's all in one? What if we chose something a lot more modern that was actually built for generating frontends quickly, effectively, in a short period of time?&lt;/p&gt;

&lt;p&gt;On the stage, we now have systems like NextJS, Astro, Tanstack Start, and Remix. All based on their own specific configuration and libraries, but all doing the same thing, in terms of pure JavaScript stacks: they add the backend directly into your project, using what is called "server-side rendering". This is done via very different methods for each, sometimes using loader methods, sometimes with server functions, or api routes, etc.&lt;/p&gt;

&lt;p&gt;These full stack libraries would usually cover both the front-end and back-end libraries (express+react would be replaced by Next or Remix), and the 4 I named above are literally just ones I know from the React world - every front-end library has its list of possible full stack frameworks. &lt;/p&gt;

&lt;p&gt;Each of those frameworks also can connect to any database or even other APIs and backends, they can do caching and SEO and so many things, that would be much harder, if not impossible, using separate React + Express stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not Industry Standard
&lt;/h2&gt;

&lt;p&gt;Some might claim that the MERN stack is somehow an industry standard, potentially citing numbers about React being the most popular front-end JavaScript framework (it is), Node being a good backend language (it is), MongoDB being very popular in node circles (it is) and Express being the most used node http server (it is!). However, those separate facts about popularity are pure cherry picking.&lt;/p&gt;

&lt;p&gt;They all stem from a forced choice of node as an engine, and JavaScript as a language, and while JS is in fact the most popular browser language (by virtue of it being the &lt;strong&gt;ONLY&lt;/strong&gt; browser language standing for decades), it is by no means the most popular &lt;em&gt;backend&lt;/em&gt; language, a position which is held by PHP. MongoDB is the most popular node database but the &lt;em&gt;actual&lt;/em&gt; most popular databases are Oracle, followed by MySQL and then Microsoft SQL server. React is the most popular JavaScript framework but it's overshadowed by a lot of other frameworks in other languages : you have Django in python, Laravel for PHP, etc. &lt;/p&gt;

&lt;p&gt;All that being said, the cherry picking is very strongly biased towards Node and JavaScript. Again, this isn't an invalid combination of technology, but it is not, in any way, "the industry standard" or even close to being the most popular.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what do I choose, then?
&lt;/h2&gt;

&lt;p&gt;That is a great question, thank you for asking! And unfortunately, the answer is that it doesn't matter, or that it depends. But here's a joyful bit of information, however: even if you do decide to go with MERN because there's a slew of popular tutorials and videos and courses, none of what you learn there will be completely lost if you move to a different choice of technology in the future. Concepts of rendering, APIs, databases, security, front-end dynamic pages... It's all good, it's all useful, it's all something you will be using in the future. &lt;/p&gt;

&lt;p&gt;So do what you like, learn what you can, but just be willing to learn new things in the future, as you define yourself in your development journey. &lt;/p&gt;

&lt;h2&gt;
  
  
  Interact with this post!
&lt;/h2&gt;

&lt;p&gt;I would love to hear your thoughts on what stack you've learned with (whether it's JavaScript or not!), and if you continued in that stack in projects, at work, etc. Did changing to a different stack or technology take time to adapt? How did you cope? Let me know in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to make an async constructor in Javascript?</title>
      <dc:creator>Lucas Lachance</dc:creator>
      <pubDate>Wed, 20 Nov 2024 01:10:53 +0000</pubDate>
      <link>https://forem.com/eslachance/how-to-make-an-async-constructor-in-javascript-142h</link>
      <guid>https://forem.com/eslachance/how-to-make-an-async-constructor-in-javascript-142h</guid>
      <description>&lt;p&gt;You're here because you have a question : how do I await a Class constructor? How do I make the constructor Async???&lt;/p&gt;

&lt;p&gt;And the answer, I'm sorry, is that you literally can't. A constructor for a class in Javascript &lt;em&gt;must&lt;/em&gt; be synchronous. However, there are alternatives in implementations that can help you do what you want. Let's explore it!&lt;/p&gt;

&lt;p&gt;You probably want this because you need to initialize something in the constructor and have it available in any call you make to the class. A good example of this would be connecting to a database and waiting for that connection to be established before accepting any queries.&lt;/p&gt;

&lt;p&gt;The pattern for this is really simple! Let's start with an example database connector, using the &lt;code&gt;sqlite&lt;/code&gt; module on npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To open this database, you need to await the &lt;code&gt;open&lt;/code&gt; function. I asked my friendly AI code helper to come up with a "DBConnector" class and it actually got the common pattern right - the one you'll see everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./database.sqlite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// exporting a singleton so there's only one connection&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd call this simply by importing it and then awaiting its calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dbconnector.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET * FROM test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, the problem here of course, is that not only do you need to manually call &lt;code&gt;myDB.connect()&lt;/code&gt; in order to start the connection, you also can't guarantee that the &lt;code&gt;query&lt;/code&gt; call will work, say, if a different file does a query as your main file is connecting.&lt;/p&gt;

&lt;p&gt;Sure, the main file can &lt;code&gt;await db.connect();&lt;/code&gt; , but anything else importing this module won't have any way to do that. And you might think, "ok but I can call &lt;code&gt;await db.connect();&lt;/code&gt; in other files too, right?" and you can... but that will reconnect to the database every time, which can be slow depending on what you're using.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Deferred Pattern
&lt;/h2&gt;

&lt;p&gt;The pattern that I came up with involves a little bit more complexity, but it remains simple and ensures that every little piece of code - and yourself - are all happy. And I did in fact come up with it on my own, even if it's actually known to others. They're called "Deferred" promises.  &lt;/p&gt;

&lt;p&gt;Here's how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// still have our imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We'll need these private properties:&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Then we make our constructor:&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// We create a new promise and store its resolve and reject&lt;/span&gt;
    &lt;span class="c1"&gt;// functions in the class instance properties.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rej&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// this is the magic, right here, basically.&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rej&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// So now, this.#defer is a promise! We can await it in other methods.&lt;/span&gt;
    &lt;span class="c1"&gt;// Now we call our this.connect *internally* and automatically.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`./database.sqlite`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="c1"&gt;// Now that we resolve the promise, any other method that awaits&lt;/span&gt;
      &lt;span class="c1"&gt;// this.#defer will continue executing.&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// in case of error we can of course reject the promise&lt;/span&gt;
      &lt;span class="c1"&gt;// any code using it would then throw an error.&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// on any action, we just await this.#defer&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Even in queries, it works perfectly fine!&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Here we KNOW that this.#db is already initialized.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now ain't that a charming little pattern? It is, of course, more code that a basic example, but personally, I think it definitely raises the bar on boilerplate code for classes that are mostly based on async methods.&lt;/p&gt;

&lt;p&gt;Let's see how to use it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dbconnector.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// it's already initialized... just use it!&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET * FROM test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// and it just works :D &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus: I made a library!
&lt;/h2&gt;

&lt;p&gt;I'm using this pattern so often that in the end, I decided to make a really quick &amp;amp; dirty library and publish it on NPM. It's called &lt;a href="https://www.npmjs.com/package/deferrals" rel="noopener noreferrer"&gt;deferrals&lt;/a&gt; and it's pretty trivial to use (it was pretty trivial to write, too, once I knew the pattern).&lt;/p&gt;

&lt;p&gt;Let's remake the above example using &lt;code&gt;deferrals&lt;/code&gt; instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// We import the library, of course.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;makeDefer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitForDefer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolveDefer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rejectDefer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deferrals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// We don't need the private properties anymore.&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Our constructor is a bit simpler.&lt;/span&gt;
    &lt;span class="nf"&gt;makeDefer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// We still call our connect method.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`./database.sqlite`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="c1"&gt;// We resolve the defer here&lt;/span&gt;
      &lt;span class="nf"&gt;resolveDefer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// or we reject it here.&lt;/span&gt;
      &lt;span class="nf"&gt;rejectDefer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We still need to await something: the defer.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitForDefer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitForDefer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DBConnector&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;'db'&lt;/code&gt; string is basically any string name that you want to give to the defer, and you can create as many as you like. Obviously you don't &lt;em&gt;need&lt;/em&gt; this library, but personally I think it's quite nice, y'know?&lt;/p&gt;

&lt;p&gt;I hope you learned a really useful pattern here, and I'm glad to have been part of your learning journey today &amp;lt;3 &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Components - just a function that returns html</title>
      <dc:creator>Lucas Lachance</dc:creator>
      <pubDate>Tue, 03 Sep 2024 17:12:02 +0000</pubDate>
      <link>https://forem.com/eslachance/react-components-just-a-function-that-returns-html-2429</link>
      <guid>https://forem.com/eslachance/react-components-just-a-function-that-returns-html-2429</guid>
      <description>&lt;p&gt;Let me make a grossly oversimplified statement that can help beginners understand React without diving too deeply into things like the "render loop" and the "shadow dom". If you just want to get the very basics of React components please read on. If you understand React internals, you should probably skip this for your own sanity. &lt;/p&gt;

&lt;p&gt;The statement is :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A React Component is simply a function that returns HTML.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This oversimplification is important to understand so many things in React, I think it's a mantra that should be integrated by any beginner. So let's repeat again : &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A React Component is simply a function that returns HTML.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's take for example this extremely simple React app which is a button with a counter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, App is a function. So that part of the statement is true as-is. &lt;/p&gt;

&lt;p&gt;The second part of my statement is &lt;em&gt;almost&lt;/em&gt; true : "it returns HTML" is technically false, because in fact there's a bunch of things that happens with the JSX ("almost html") returned by the component. But if we imagine for a second this is just HTML, then you can just think : this html is being put inside the webpage.&lt;/p&gt;

&lt;p&gt;Is that simple enough? Good! I knew you would get it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'll call the return of a component JSX from now on because I've triggered enough people already.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But there's a 3rd part of the sentence that I omitted until now. David's &lt;em&gt;secret chord&lt;/em&gt; as it were, which will definitely please the Lord.&lt;/p&gt;

&lt;p&gt;A React Component is simply a function &lt;em&gt;that runs every time its state or props change&lt;/em&gt; which returns JSX.&lt;/p&gt;

&lt;p&gt;This new part explains exactly how React is "reactive", the core of its idea. When the state changes, the component renders again. That means, in simple terms, that the function runs again, and returns updated JSX.&lt;/p&gt;

&lt;p&gt;This means that when &lt;code&gt;setCount&lt;/code&gt; is called, the component function runs again, and this time, &lt;code&gt;const [count, setCount] = useState(0);&lt;/code&gt; is going to ignore the default &lt;code&gt;0&lt;/code&gt; value, and use the new state value instead. Which is why when it reaches the JSX, that value of &lt;code&gt;count&lt;/code&gt; is put in the JSX, and that then goes to update the webpage. &lt;/p&gt;

&lt;h2&gt;
  
  
  So why does this matter?
&lt;/h2&gt;

&lt;p&gt;The entire reason I wrote this short article is to explain one thing : "state updates are asynchronous". It's a common misunderstanding of React. Let's change the example code for the counter a little bit to demonstrate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what's going to happen here? What will be the output of the &lt;code&gt;console.log&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; and what will it be &lt;em&gt;after&lt;/em&gt;? &lt;/p&gt;

&lt;p&gt;If you said "0, then 1" on the first click... you forgot something extremely basic about javascript: &lt;strong&gt;You defined &lt;code&gt;count&lt;/code&gt; with CONST&lt;/strong&gt;. How would the value possibly change on a const??? So the answer is, they're both going to be &lt;code&gt;0&lt;/code&gt;. Then they're both going to be &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So how &lt;em&gt;do&lt;/em&gt; you get the new value of a state within a function in your component? Well, simply, you don't. Rather than doing &lt;code&gt;setCount(count + 1)&lt;/code&gt; what you do instead is &lt;code&gt;const newCount = count + 1&lt;/code&gt; and then you can &lt;code&gt;console.log(newcount)&lt;/code&gt; and also &lt;code&gt;setCount(newCount)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And what if you are doing some complex operation in the state and you can't do it outside because it's a functional setstate? In that case, you can rely on the new state via a useEffect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new count value : &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the change in state triggers the component to render again and run the function, useEffect will be checked. And since it has a dependency on the &lt;code&gt;count&lt;/code&gt; state which changed, it'll execute the body of the useEffect, and log the change!&lt;/p&gt;

&lt;p&gt;Hopefully this clarifies the very basic idea: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;A React Component is only a function that runs when its state or props change, and returns JSX.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Stop using create-react-app</title>
      <dc:creator>Lucas Lachance</dc:creator>
      <pubDate>Sat, 24 Aug 2024 15:19:32 +0000</pubDate>
      <link>https://forem.com/eslachance/stop-using-create-react-app-7in</link>
      <guid>https://forem.com/eslachance/stop-using-create-react-app-7in</guid>
      <description>&lt;p&gt;This is a cry for help. I beg you, I am on my knees, weeping, imploring you...&lt;/p&gt;

&lt;h2&gt;
  
  
  STOP USING CREATE-REACT-APP
&lt;/h2&gt;

&lt;p&gt;Ok so if you don't want to read the whole article let me tell you what's what in simple terms (TL;DR):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;create-react-app&lt;/code&gt; stopped being updated over 2 years ago&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;react-scripts&lt;/code&gt; which CRA depends on, stopped being updated over 2 years ago&lt;/li&gt;
&lt;li&gt;CRA is &lt;strong&gt;slow&lt;/strong&gt; compared to modern alternatives&lt;/li&gt;
&lt;li&gt;webpack is &lt;strong&gt;very slow&lt;/strong&gt; compared to modern alternatives&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the solution? In one word: &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Longer Updated
&lt;/h3&gt;

&lt;p&gt;The last time the &lt;code&gt;create-react-app&lt;/code&gt; package was updated was on &lt;em&gt;April 12 2022 at 1:33 EDT&lt;/em&gt;, which by all accounts as of writing this, is over 2 years ago. And while &lt;em&gt;some&lt;/em&gt; things can go years without updating, it's important to realize that CRA itself has a lot of dependencies which have not been updated, and have suffered from vulnerabilities. When you run &lt;code&gt;npx create-react-app&lt;/code&gt; you'll get the following result:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;8 vulnerabilities (2 moderate, 6 high)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The Facebook/React team have no intention at this point of fixing any dependency, as made clear by the fact that create-react-app is no longer updated and they now recommend other tools (see further down).&lt;/p&gt;

&lt;h3&gt;
  
  
  React-Scripts
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;react-scripts&lt;/code&gt; is the actual dependency used by CRA when running your dev server, with &lt;code&gt;npm run dev&lt;/code&gt; and when building with &lt;code&gt;npm run build&lt;/code&gt;. And just like CRA, its last update was in 2022, in fact, in the exact same commit as CRA's last update. react-scripts has a &lt;em&gt;ton&lt;/em&gt; of dependencies that have since updated and patched, but of course, react-scripts won't update. &lt;/p&gt;

&lt;h3&gt;
  
  
  Webpack
&lt;/h3&gt;

&lt;p&gt;I don't want to &lt;em&gt;bash&lt;/em&gt; webpack here, but I will say this : webpack is slow as shit, compared to Vite. It's not as configurable as the alternative either, even if it seems to have plenty of a plugin ecosystem, it's already been overshadowed by what Vite offers. &lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: Vite
&lt;/h2&gt;

&lt;p&gt;Vite (pronounced somewhere between &lt;code&gt;vit&lt;/code&gt; and &lt;code&gt;veet&lt;/code&gt; since it's the French word for "Fast") is a &lt;em&gt;direct&lt;/em&gt; replacement for create-react-app's features, in that it offers a fully configurable development environment with a hot reload server and plenty of plugins.&lt;/p&gt;

&lt;p&gt;Not only is Vite &lt;em&gt;configurable&lt;/em&gt;, it's &lt;em&gt;blazing fast&lt;/em&gt; and it also supports &lt;em&gt;basically all front-end frameworks&lt;/em&gt;. That is to say, you can create a Vite project for React, Svelte, Solid, Vue, Lit, Quik, and Angular. It even lets you create vanillajs applications but with builder dependencies such as tailwind, sass, etc.&lt;/p&gt;

&lt;p&gt;Personal anecdote time : When I first learned of Vite in a previous job, I took half a day to convert a project that was using &lt;code&gt;react-scripts&lt;/code&gt; into Vite. It took half a day because it was a pretty &lt;em&gt;massive&lt;/em&gt; project, I was a Junior level dev, and I was new to a lot of it. I knew it was worth it, and I was right : When saving a file and waiting for the hot reload in the browser, the waiting time went straight down from &lt;strong&gt;&lt;em&gt;6 MINUTES&lt;/em&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;em&gt;LESS THAN A SECOND&lt;/em&gt;&lt;/strong&gt;. Yes, you're reading that right, I didn't make a typo between "minutes" and "seconds". The initial build time also was reduced to about 20 seconds, because it was still a pretty massive application. &lt;/p&gt;

&lt;p&gt;So when I say "blazing fast" I actually do mean it, it is not a hyperbole or exaggeration. And I'm going to do it again, and again, in every project I work on still using react-scripts.&lt;/p&gt;

&lt;p&gt;So, have I convinced you? Go right ahead and &lt;a href="https://vitejs.dev/guide/" rel="noopener noreferrer"&gt;get started with Vite today&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to convert
&lt;/h2&gt;

&lt;p&gt;Ok so you might be wondering if there's going to be a whole lot of changes to make in your code, right? Well... not really. The truth of the matter is that the vast majority of your changes happen at the configuration and root level of the app. &lt;/p&gt;

&lt;p&gt;Converting a CRA app into a Vite one boils down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From a new folder (not your existing app), run &lt;code&gt;npm create vite@latest&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;React&lt;/code&gt; as a framework&lt;/li&gt;
&lt;li&gt;Choose &lt;code&gt;Javascript + SWC&lt;/code&gt; or &lt;code&gt;Typescript + SWC&lt;/code&gt; depending on whether you use TS. (SWC makes the build process even faster than not using it)&lt;/li&gt;
&lt;li&gt;Let it generate the scaffold project&lt;/li&gt;
&lt;li&gt;Copy over all your components and subfolders (EXCEPT FOR &lt;code&gt;App.js&lt;/code&gt; and &lt;code&gt;index.js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Modify the &lt;code&gt;main.jsx&lt;/code&gt; and &lt;code&gt;App.jsx&lt;/code&gt; to re-introduce your configuration including react-router, your contexts, etc&lt;/li&gt;
&lt;li&gt;Add any &lt;a href="https://vitejs.dev/plugins/" rel="noopener noreferrer"&gt;required plugins&lt;/a&gt; into &lt;code&gt;vite.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adjust for errors/issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously the last 3 steps are where the majority of your work will go. Depending on the complexity of your existing application, finding the &lt;a href="https://vitejs.dev/plugins/" rel="noopener noreferrer"&gt;correct plugin&lt;/a&gt; and &lt;a href="https://vitejs.dev/config/" rel="noopener noreferrer"&gt;configuration&lt;/a&gt; might take a bit of time, and adjusting for errors you might encounter could take some time. But in the end, I repeat again that it will absolutely be worth the effort. &lt;/p&gt;

&lt;h2&gt;
  
  
  What if I need help?
&lt;/h2&gt;

&lt;p&gt;If you've reached this far and you've decided to switch but are afraid of having to deal with problems and errors, I invite you to join me in the #javascript channel of &lt;a href="https://discord.gg/programming" rel="noopener noreferrer"&gt;The Programmer's Hangout on Discord&lt;/a&gt;. I hang out there as &lt;code&gt;eslachance&lt;/code&gt; (usually nicknamed Alterion), don't hesitate to ping me for help and mention this dev.to article. The more official &lt;a href="https://discord.gg/reactiflux" rel="noopener noreferrer"&gt;Reactiflux&lt;/a&gt; server is also at your disposal.&lt;/p&gt;

&lt;p&gt;If I'm not available there are plenty of people in TPH and Reactiflux that can help you, some that I've directly converted to Vite!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Conspiracy Theory
&lt;/h2&gt;

&lt;p&gt;Stop reading here if you don't care about drama, conspiracy theories, and rants. I'm about to go deep into a rabbit hole which you're absolutely not forced to follow me into - Vite's cool as it is, it's your answer, you may disengage for the rest ;) &lt;/p&gt;

&lt;p&gt;The question I asked myself often is : Why did the React team bury the mention of Vite deep within a collapsed "Deep Dive" block on the &lt;a href="https://react.dev/learn/start-a-new-react-project" rel="noopener noreferrer"&gt;Start a New Project&lt;/a&gt; page of their docs. Why does the mention of Vite feel very brushed off, just a comment, a maybe not important note at the very end of a wall of text most people won't read? &lt;/p&gt;

&lt;p&gt;What I &lt;em&gt;think&lt;/em&gt; should have happened is that instead of this massive hidden wall of text casually handing out a mention of Vite along with Parcel... it should have been a paragraph at the top level of the page, &lt;strong&gt;before&lt;/strong&gt; any mention of NextJS and other full-stack frameworks. &lt;/p&gt;

&lt;p&gt;The page should have noted that &lt;code&gt;create-react-app&lt;/code&gt; is deprecated (it makes NO mention of CRA at all!) and that its direct, suggested replacement for a front-end-only project was to use Vite. &lt;/p&gt;

&lt;p&gt;Instead, what the documentation does is suggest to use a "Production-grade React framework", and starts with NextJS as the main one, the first one.&lt;/p&gt;

&lt;p&gt;Here's where the &lt;em&gt;conspiracy&lt;/em&gt; comes in. NextJS is made by Vercel, who also offers hosting that is &lt;em&gt;specifically&lt;/em&gt; compatible with NextJS, which is &lt;strong&gt;not hostable&lt;/strong&gt; unless you are on a service that supports it. Even if the docs say &lt;code&gt;All of the frameworks we recommend are open source with active communities for support, and can be deployed to your own server or a hosting provider&lt;/code&gt; , it fails to mention that the hosting or server requires nodejs to be running for this to work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am aware of NextJS's "static output" but that &lt;a href="https://nextjs.org/docs/pages/building-your-application/deploying/static-exports#unsupported-features" rel="noopener noreferrer"&gt;doesn't support most of its features&lt;/a&gt; and more importantly, isn't an SPA but rather a Static Site Generator where every page is reloaded, just what React avoids happening.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now... Vercel is a large company, and they have been infiltrating themselves into the React ecosystem. As &lt;a href="https://www.reddit.com/r/reactjs/comments/14uqjd5/state_of_react_nextjs_vercel/" rel="noopener noreferrer"&gt;one reddit post&lt;/a&gt; points out: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The React team is currently working primarily with Vercel to "research, develop, integrate, and test framework-agnostic bleeding-edge React features like React Server Components". The React docs website is built on NextJs."&lt;/li&gt;
&lt;li&gt;"Vercel has been more aggressive in hiring and sponsoring React core team members."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now... it doesn't &lt;em&gt;source&lt;/em&gt; these facts, so take it with a grain of salt (I haven't been able to seriously find any source for these on my own. that's why it's a conspiracy &lt;em&gt;theory&lt;/em&gt; and not an affirmation of facts). But it sure makes me wonder just how much money Vercel has been pumping into the React team, how many members of that team it stole and how that affected the React docs and the team itself, either directly or through "my colleague used to work here and now is at Vercel and they keep telling me Next is great".&lt;/p&gt;

&lt;p&gt;If you have any solid information on the subject I would &lt;strong&gt;love&lt;/strong&gt; to hear from you in private, do a little bit of investigative journalism, and write up a real article or video on the matter. But until then, it'll remain just real life conspiracy theory I'll continue to believe in until an official Facebook/React team member explains to me why the hell Vite isn't put front and center in their docs.&lt;/p&gt;

&lt;p&gt;That's all, folks!&lt;/p&gt;

&lt;h2&gt;
  
  
  EDIT 2025-01-19 : More Info
&lt;/h2&gt;

&lt;p&gt;Ok so I have actually learned a few things regarding the above conspiracy which does go against it, somewhat. This is all second-hand information but it does come from trusted sources in the React ecosystem. &lt;/p&gt;

&lt;p&gt;The idea is that the React team, for the last 2 years, have been thinking about how to specifically handle either a CRA &lt;em&gt;update&lt;/em&gt; or a proper graceful deprecation. &lt;/p&gt;

&lt;p&gt;On the one hand, updating CRA, for the React team, would mean supporting more than just a standard webpack "front-end only" react scaffold, since they're now neck-deep in pushing Server Components down everyone's gullet (I'm opinionated about this and against it as you might tell). So this would mean making a CLI that supports multiple methods of creating such apps, a bit like Vite does, but obviously &lt;em&gt;only&lt;/em&gt; for the React ecosystem, and that takes planning and time. &lt;/p&gt;

&lt;p&gt;On the other hand, deprecating it means guiding people to different places and different tools that replaces it. Now, it's not necessarily that they don't like Vite, it's that they want to give everyone a fair shake when talking about that deprecation. One specific example : &lt;a href="https://parceljs.org/docs/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt; which wants to be a competing system to vite (and, imho, failing miserably at it, sorry Devon), and so wants a seat at the table of "hey now that CRA doesn't work, use THIS instead". The React team would want to list some tools, but at the same time, probably that's a list that would eventually need to be upgraded so there's definitely a lot of planning required here, too. &lt;/p&gt;

&lt;p&gt;All in all, if all this is correct (and I have no actual reason to doubt it at this point) then there's still the problem of the React team just... missing their window of opportunity. The bigger issue at hand is that CRA isn't just deprecated now, it's completely broken, since the release of React 19, since CRA doesn't support it. So all this time wasted on thinking about it because they didn't want to lose the exposure and "brand recognition" of create-react-app means that now, create-react-app is broken and will continue to bleed usage as we all continue to tell people not to use it since vitejs works perfectly fine. &lt;/p&gt;

&lt;p&gt;React team, you missed your window. Please admit defeat or make a decision already.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>vite</category>
    </item>
    <item>
      <title>Fixing CORS in your SPA</title>
      <dc:creator>Lucas Lachance</dc:creator>
      <pubDate>Mon, 12 Aug 2024 18:24:45 +0000</pubDate>
      <link>https://forem.com/eslachance/fixing-cors-in-your-spa-dfg</link>
      <guid>https://forem.com/eslachance/fixing-cors-in-your-spa-dfg</guid>
      <description>&lt;p&gt;An extremely common issue that plagues new web developers trying to establish communication between their front-end project and a backend or API, is the almighty CORS error. You know what I'm talking about, it's the one that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Access to fetch at 'http://localhost:3000/' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What others say
&lt;/h2&gt;

&lt;p&gt;When doing research on this, you'll probably find a lot of different potential solutions, including adding &lt;code&gt;"credentials": "include"&lt;/code&gt; in your request (WRONG!), &lt;code&gt;"mode": "no-cors"&lt;/code&gt; (WRONG AGAIN!), or having to modify your backend to add CORS headers such as &lt;code&gt;app.use(cors())&lt;/code&gt; in express (functional, but not always possible or ideal).&lt;/p&gt;

&lt;p&gt;I'm here to tell you there's a better way. An easier way. One that will make a lot of sense for a lot of people, especially those getting started on simple projects. &lt;/p&gt;

&lt;h2&gt;
  
  
  Not an absolute solution
&lt;/h2&gt;

&lt;p&gt;I want to clarify that I'm here to address a very particular situation that does not apply to every single case out there. This only applies if you are:&lt;/p&gt;

&lt;p&gt;Using a front-end javascript-based Single-Page-Application (SPA), such as: React, Vue, Svelte, SolidJS, Angular, Astro, or any purely frontend SPA, &lt;strong&gt;OR&lt;/strong&gt; you are using vanilla javascript but with a development server like &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That is it. I will explain examples using both Vite as well as the (very deprecated and dead) create-react-app, but the concept should apply to any frontend framework with a development server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: full-stack frameworks such as Next, Nuxt, Solid-Start, etc, won't need this unless you're accessing a secondary backend, but this should be done via the actual backend provided by that framework so is beyond the scope of this article.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why the error happens
&lt;/h2&gt;

&lt;p&gt;Some optional background information, you can skip this if you only want a solution.&lt;/p&gt;

&lt;p&gt;The TL;DR of the CORS error is that a backend server made for a frontend can (and should) only allow for http queries made by a known frontend from a known URL. That is to say, if I'm the owner of &lt;code&gt;my-domain-name.com&lt;/code&gt; , I have a backend that's running on &lt;code&gt;my-domain-name.com/api&lt;/code&gt; or &lt;code&gt;api.my-domain-name.com&lt;/code&gt; , I want to &lt;em&gt;only&lt;/em&gt; accept requests made from my-domain-name.com. This prevents any request from other domain names.&lt;/p&gt;

&lt;p&gt;To explain a very clear, unambiguous example: Let's say you're &lt;code&gt;bankofamerica.com&lt;/code&gt;. You do not want someone to register &lt;code&gt;bankofamerlca.com&lt;/code&gt; and be able to show a proper login screen, where people would enter their real Bank of America login and password, check them against your backend, before stealing them... right? That's what CORS is mostly for. &lt;/p&gt;

&lt;p&gt;It's also why CORS errors don't affect requests made from another server, or through a proxy : because it's meant to protect a normal end user at home, with no technical know-how, from being a victim of very simple phishing attempts. That can still happen, of course, but it's part of that ongoing battle against scammers and thieves. &lt;/p&gt;

&lt;p&gt;But, you might actually want to allow for requests to be made from more than one origin (if you own more than one domain, for example) or from any origin (if you have a public-facing API or service anyone can access). That's why CORS is &lt;em&gt;configurable&lt;/em&gt; via the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header, and why adding &lt;code&gt;app.use(cors())&lt;/code&gt; in express works, for example.&lt;/p&gt;

&lt;p&gt;But enough background, let's go to the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution, in development
&lt;/h2&gt;

&lt;p&gt;Statistically speaking, you're probably doing your development in React, so let's address the most popular option first. &lt;/p&gt;

&lt;p&gt;React developers will be using one of the two following development environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create-React-App
&lt;/h3&gt;

&lt;p&gt;If you are using &lt;code&gt;create-react-app&lt;/code&gt;, consider moving to &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; as soon as you can, since &lt;a href="https://dev.to/eslachance/stop-using-create-react-app-7in"&gt;CRA is deprecated&lt;/a&gt;. However, here's the solution anyways because I'm not your mother and I don't make your choices.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://create-react-app.dev/docs/proxying-api-requests-in-development" rel="noopener noreferrer"&gt;&lt;em&gt;Source documentation&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To add a proxy, you can simply open your &lt;code&gt;package.json&lt;/code&gt; and add the following line at the top level of the json structure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;"proxy": "http://localhost:3000",&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You must obviously change the localhost address to &lt;em&gt;your&lt;/em&gt; backend URL. You also need to modify all your HTTP requests made with &lt;code&gt;fetch()&lt;/code&gt; or &lt;code&gt;axios&lt;/code&gt; to start with &lt;code&gt;/api&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example if you were previously calling &lt;code&gt;http://localhost:3000/login&lt;/code&gt; , you would change that to &lt;code&gt;/api/login&lt;/code&gt;. The backend would then need to respond do the &lt;code&gt;/login&lt;/code&gt; route in this case. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Advanced Configuration&lt;/em&gt; needs to be done via the &lt;code&gt;src/setupProxy.js&lt;/code&gt; file but should not be required in this case. See &lt;a href="https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually" rel="noopener noreferrer"&gt;more documentation&lt;/a&gt; on the subject.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vite
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://vitejs.dev/config/server-options.html#server-proxy" rel="noopener noreferrer"&gt;&lt;em&gt;Source Documentation&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A number of frontend frameworks now rely on Vite to provide a fast and efficient development environment with hot module reload (that means, updating the page when you save a file!). Whether it's React, Vue, Svelte, Solid, or even vanilla javascript, you'll find a boilerplate available by running &lt;code&gt;npm create vite@latest&lt;/code&gt; and choosing your framework and other options.&lt;/p&gt;

&lt;p&gt;Once you have your Vite project running, setting up the proxy is as easy as updating &lt;code&gt;vite.config.js&lt;/code&gt; to add the &lt;code&gt;proxy&lt;/code&gt; configuration, as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You only need the proxy line in the server object here - the rest of your configuration does not need to match the above. Note that in the default case, requests made to the backend will be prepended with &lt;code&gt;/api&lt;/code&gt;, meaning if you call &lt;code&gt;/api/login&lt;/code&gt; , the backend call that will be made will be on &lt;code&gt;http://localhost:3000/api/login&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So that means all your backend calls go from something like &lt;code&gt;fetch("http://localhost:3000/endpoint")&lt;/code&gt; to &lt;code&gt;fetch("/api/endpoint")&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Advanced Configuration&lt;/em&gt; is necessary to remove the &lt;code&gt;/api&lt;/code&gt; prefix in the calls
&lt;/h4&gt;

&lt;p&gt;You can use a slightly more advanced configuration on Vite to remove the &lt;code&gt;/api&lt;/code&gt; prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;rewrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;api/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it's not that hard, just a simple regex replace.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about PRODUCTION???
&lt;/h2&gt;

&lt;p&gt;Some of you might be wondering what happens when you push your code to production, as in, when you deploy it to your hosting. There are obviously a large number of possible situations that might arise, but let me cover a few. Before that, I want to clear out a misconception.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Your proxy configuration and development server are not relevant to production or deployment to a hosting service&lt;/strong&gt;. That is to say, your development server is just that, development. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important thing to understand is that invariable in SPAs, to create your production build, you must run a command like &lt;code&gt;npm run build&lt;/code&gt;, which creates a new folder in your project called &lt;code&gt;build/&lt;/code&gt; or &lt;code&gt;output/&lt;/code&gt;. This will contain a small number of files in html, js, and css format, and that is your &lt;em&gt;static production output&lt;/em&gt;. From here, this is where the solutions stem from.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1: Backend Serves Static Files
&lt;/h3&gt;

&lt;p&gt;The very first, simplest, and probably most valid solution for you, is to serve the &lt;code&gt;build&lt;/code&gt; folder files directly from your existing backend server. This obviously only relates if &lt;em&gt;you're&lt;/em&gt; the one making the backend, and it's why I noted that using &lt;code&gt;app.use(cors())&lt;/code&gt; wasn't the best way... Because if you simply serve your static files from the backend, you can skip the whole CORS problem in production too!&lt;/p&gt;

&lt;p&gt;For example, if you have an &lt;code&gt;express.js&lt;/code&gt; backend, you could simply copy over your &lt;code&gt;build&lt;/code&gt; folder into the express project, and use the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// your other routes here!&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="c1"&gt;// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, that would work perfectly well. It does imply you copy over the files all the time however. The &lt;a href="https://expressjs.com/en/starter/static-files.html" rel="noopener noreferrer"&gt;express docs&lt;/a&gt; indicate you can also call another folder but it's a bit more complex, so I won't go into that.&lt;/p&gt;

&lt;p&gt;This solution works with koa, fastify, hono, and probably any other nodejs backend, they each have an equivalent to &lt;code&gt;express.static()&lt;/code&gt;. If you're not in nodejs, look up your docs on how to do it in your prefered backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 2: An HTTP Server Proxy
&lt;/h3&gt;

&lt;p&gt;Let's say you don't want to use the backend to serve static files. You can reproduce a similar proxy configuration from your development, into a production http server. This is possible in Apache, Nginx, IIS, or any other http server that has this proxy capability.&lt;/p&gt;

&lt;p&gt;For example, an nginx.conf would look like this for static files + express:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
  listen 80;
  server_name example.com;
  location / {
    root /path/to/build/folder;
    index index.html;
  }
  location /api {
    proxy_pass http://localhost:3000;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's another quick example with Apache (The &lt;code&gt;ProxyPass&lt;/code&gt; line is all you would need) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="err"&gt;*:80&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ServerName example.com
        DocumentRoot /var/www/backup
        ProxyPass /api http://localhost:3000/api/
        &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="err"&gt;/var/www/backup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                Require all granted
                Options +Indexes
                AllowOverride None
                Order allow,deny
                Allow from all
        &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the proxy address above doesn't need to be on the same machine - this can work even if you're hosting the frontend and backend on completely different services!&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 3: Actually using CORS
&lt;/h3&gt;

&lt;p&gt;So what if you actually need to have a separate frontend and backend hosted on a completely different domain name, and you can't use a reverse proxy on your web server, and you have absolutely no way to do this any other method than API calls being on a different origin? THAT is when you need to think about CORS.&lt;/p&gt;

&lt;p&gt;The very basics of CORS is extremely simple. You just need to add a header to any outgoing request sent from your backend server. The frontend &lt;em&gt;cannot&lt;/em&gt; control this, it has to be a backend response header, period.&lt;/p&gt;

&lt;p&gt;The header will look like &lt;code&gt;Access-Control-Allow-Origin: https://example.com&lt;/code&gt; for a specific domain name, &lt;code&gt;Access-Control-Allow-Origin: http://somedomain.com:8080&lt;/code&gt; for, say, something on a different port, or if you really want to let anyone access your service, &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It's not possible to add more than one ACAO header, or add more than one domain to the header. In order to support multiple origin domains, you would need backend logic that modifies this header to allow for the one doing the request. Most CORS libraries for your backend should have that capability, but obviously it's beyond the scope of this tutorial.&lt;/p&gt;

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

&lt;p&gt;That's all, folks! Hopefully this extensive and verbose (sorry!) post is enough for you to understand why CORS errors happen, how to resolve them while you're developing your website, and even how to deal with them in production. If you have any questions, please don't hesitate to ask below and I'll try my best to help! 💖&lt;/p&gt;

</description>
      <category>cors</category>
      <category>development</category>
      <category>frameworks</category>
      <category>react</category>
    </item>
  </channel>
</rss>
